blob: b66e2585958c47a46aaed268a810748bad2f8711 [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 Holmberg12161f42013-02-21 11:30:02 -07004 * Copyright (c) 2009-2013, The Linux Foundation. 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>
Jeff Hugo5ba15fe2013-05-06 14:24:24 -060024#include <mach/msm_smem.h>
Brian Swetland03e00cd2009-07-01 17:58:37 -070025
26#include "smd_private.h"
Jeff Hugo5ba15fe2013-05-06 14:24:24 -060027#include "smem_private.h"
Brian Swetland03e00cd2009-07-01 17:58:37 -070028
29#if defined(CONFIG_DEBUG_FS)
30
31static char *chstate(unsigned n)
32{
33 switch (n) {
34 case SMD_SS_CLOSED:
35 return "CLOSED";
36 case SMD_SS_OPENING:
37 return "OPENING";
38 case SMD_SS_OPENED:
39 return "OPENED";
40 case SMD_SS_FLUSHING:
41 return "FLUSHING";
42 case SMD_SS_CLOSING:
43 return "CLOSING";
44 case SMD_SS_RESET:
45 return "RESET";
46 case SMD_SS_RESET_OPENING:
47 return "ROPENING";
48 default:
49 return "UNKNOWN";
50 }
51}
52
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070053static int debug_f3(char *buf, int max)
Brian Swetland03e00cd2009-07-01 17:58:37 -070054{
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070055 char *x;
56 int size;
57 int i = 0, j = 0;
58 unsigned cols = 0;
59 char str[4*sizeof(unsigned)+1] = {0};
Brian Swetland03e00cd2009-07-01 17:58:37 -070060
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070061 i += scnprintf(buf + i, max - i,
62 "Printing to log\n");
63
64 x = smem_get_entry(SMEM_ERR_F3_TRACE_LOG, &size);
65 if (x != 0) {
66 pr_info("smem: F3 TRACE LOG\n");
67 while (size > 0) {
68 if (size >= sizeof(unsigned)) {
69 pr_info("%08x", *((unsigned *) x));
70 for (j = 0; j < sizeof(unsigned); ++j)
71 if (isprint(*(x+j)))
72 str[cols*sizeof(unsigned) + j]
73 = *(x+j);
74 else
75 str[cols*sizeof(unsigned) + j]
76 = '-';
77 x += sizeof(unsigned);
78 size -= sizeof(unsigned);
79 } else {
80 while (size-- > 0)
81 pr_info("%02x", (unsigned) *x++);
82 break;
83 }
84 if (cols == 3) {
85 cols = 0;
86 str[4*sizeof(unsigned)] = 0;
87 pr_info(" %s\n", str);
88 str[0] = 0;
89 } else {
90 cols++;
91 pr_info(" ");
92 }
93 }
94 pr_info("\n");
95 }
96
97 return max;
Brian Swetland03e00cd2009-07-01 17:58:37 -070098}
99
Eric Holmberg7ad623a2012-03-01 14:41:10 -0700100static int debug_int_stats(char *buf, int max)
101{
102 int i = 0;
103 int subsys;
104 struct interrupt_stat *stats = interrupt_stats;
105 const char *subsys_name;
106
107 i += scnprintf(buf + i, max - i,
Eric Holmberg12161f42013-02-21 11:30:02 -0700108 " Subsystem | Interrupt ID | In | Out (Hardcoded) |"
109 " Out (Configured)|\n");
Eric Holmberg7ad623a2012-03-01 14:41:10 -0700110
111 for (subsys = 0; subsys < NUM_SMD_SUBSYSTEMS; ++subsys) {
112 subsys_name = smd_pid_to_subsystem(subsys);
113 if (subsys_name) {
114 i += scnprintf(buf + i, max - i,
Eric Holmberg12161f42013-02-21 11:30:02 -0700115 "%-10s %4s | %9d | %9u | %9u | %9u |\n",
Eric Holmberg7ad623a2012-03-01 14:41:10 -0700116 smd_pid_to_subsystem(subsys), "smd",
Arun Kumar Neelakantamac7c02d2012-10-16 22:17:55 +0530117 stats->smd_interrupt_id,
Eric Holmberg7ad623a2012-03-01 14:41:10 -0700118 stats->smd_in_count,
119 stats->smd_out_hardcode_count,
120 stats->smd_out_config_count);
121
122 i += scnprintf(buf + i, max - i,
Eric Holmberg12161f42013-02-21 11:30:02 -0700123 "%-10s %4s | %9d | %9u | %9u | %9u |\n",
Eric Holmberg7ad623a2012-03-01 14:41:10 -0700124 smd_pid_to_subsystem(subsys), "smsm",
Arun Kumar Neelakantamac7c02d2012-10-16 22:17:55 +0530125 stats->smsm_interrupt_id,
Eric Holmberg7ad623a2012-03-01 14:41:10 -0700126 stats->smsm_in_count,
127 stats->smsm_out_hardcode_count,
128 stats->smsm_out_config_count);
129 }
130 ++stats;
131 }
132
133 return i;
134}
135
136static int debug_int_stats_reset(char *buf, int max)
137{
138 int i = 0;
139 int subsys;
140 struct interrupt_stat *stats = interrupt_stats;
141
142 i += scnprintf(buf + i, max - i, "Resetting interrupt stats.\n");
143
144 for (subsys = 0; subsys < NUM_SMD_SUBSYSTEMS; ++subsys) {
145 stats->smd_in_count = 0;
146 stats->smd_out_hardcode_count = 0;
147 stats->smd_out_config_count = 0;
148 stats->smsm_in_count = 0;
149 stats->smsm_out_hardcode_count = 0;
150 stats->smsm_out_config_count = 0;
151 ++stats;
152 }
153
154 return i;
155}
156
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700157static int debug_diag(char *buf, int max)
158{
159 int i = 0;
160
161 i += scnprintf(buf + i, max - i,
162 "Printing to log\n");
163 smd_diag();
164
165 return i;
166}
167
168static int debug_modem_err_f3(char *buf, int max)
169{
170 char *x;
171 int size;
172 int i = 0, j = 0;
173 unsigned cols = 0;
174 char str[4*sizeof(unsigned)+1] = {0};
175
176 x = smem_get_entry(SMEM_ERR_F3_TRACE_LOG, &size);
177 if (x != 0) {
178 pr_info("smem: F3 TRACE LOG\n");
179 while (size > 0 && max - i) {
180 if (size >= sizeof(unsigned)) {
181 i += scnprintf(buf + i, max - i, "%08x",
182 *((unsigned *) x));
183 for (j = 0; j < sizeof(unsigned); ++j)
184 if (isprint(*(x+j)))
185 str[cols*sizeof(unsigned) + j]
186 = *(x+j);
187 else
188 str[cols*sizeof(unsigned) + j]
189 = '-';
190 x += sizeof(unsigned);
191 size -= sizeof(unsigned);
192 } else {
193 while (size-- > 0 && max - i)
194 i += scnprintf(buf + i, max - i,
195 "%02x",
196 (unsigned) *x++);
197 break;
198 }
199 if (cols == 3) {
200 cols = 0;
201 str[4*sizeof(unsigned)] = 0;
202 i += scnprintf(buf + i, max - i, " %s\n",
203 str);
204 str[0] = 0;
205 } else {
206 cols++;
207 i += scnprintf(buf + i, max - i, " ");
208 }
209 }
210 i += scnprintf(buf + i, max - i, "\n");
211 }
212
213 return i;
214}
215
216static int debug_modem_err(char *buf, int max)
217{
218 char *x;
219 int size;
220 int i = 0;
221
222 x = smem_find(ID_DIAG_ERR_MSG, SZ_DIAG_ERR_MSG);
223 if (x != 0) {
224 x[SZ_DIAG_ERR_MSG - 1] = 0;
225 i += scnprintf(buf + i, max - i,
226 "smem: DIAG '%s'\n", x);
227 }
228
229 x = smem_get_entry(SMEM_ERR_CRASH_LOG, &size);
230 if (x != 0) {
231 x[size - 1] = 0;
232 i += scnprintf(buf + i, max - i,
233 "smem: CRASH LOG\n'%s'\n", x);
234 }
235 i += scnprintf(buf + i, max - i, "\n");
236
237 return i;
238}
239
240static int debug_read_diag_msg(char *buf, int max)
Brian Swetland03e00cd2009-07-01 17:58:37 -0700241{
242 char *msg;
243 int i = 0;
244
245 msg = smem_find(ID_DIAG_ERR_MSG, SZ_DIAG_ERR_MSG);
246
Brian Swetland03e00cd2009-07-01 17:58:37 -0700247 if (msg) {
248 msg[SZ_DIAG_ERR_MSG - 1] = 0;
249 i += scnprintf(buf + i, max - i, "diag: '%s'\n", msg);
250 }
251 return i;
252}
253
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700254static int dump_ch(char *buf, int max, int n,
Jeff Hugo918b2dc2012-03-21 13:42:09 -0600255 void *half_ch_s,
256 void *half_ch_r,
257 struct smd_half_channel_access *half_ch_funcs,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700258 unsigned size)
259{
Brian Swetland03e00cd2009-07-01 17:58:37 -0700260 return scnprintf(
261 buf, max,
262 "ch%02d:"
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700263 " %8s(%04d/%04d) %c%c%c%c%c%c%c%c <->"
264 " %8s(%04d/%04d) %c%c%c%c%c%c%c%c : %5x\n", n,
Jeff Hugo918b2dc2012-03-21 13:42:09 -0600265 chstate(half_ch_funcs->get_state(half_ch_s)),
266 half_ch_funcs->get_tail(half_ch_s),
267 half_ch_funcs->get_head(half_ch_s),
268 half_ch_funcs->get_fDSR(half_ch_s) ? 'D' : 'd',
269 half_ch_funcs->get_fCTS(half_ch_s) ? 'C' : 'c',
270 half_ch_funcs->get_fCD(half_ch_s) ? 'C' : 'c',
271 half_ch_funcs->get_fRI(half_ch_s) ? 'I' : 'i',
272 half_ch_funcs->get_fHEAD(half_ch_s) ? 'W' : 'w',
273 half_ch_funcs->get_fTAIL(half_ch_s) ? 'R' : 'r',
274 half_ch_funcs->get_fSTATE(half_ch_s) ? 'S' : 's',
275 half_ch_funcs->get_fBLOCKREADINTR(half_ch_s) ? 'B' : 'b',
276 chstate(half_ch_funcs->get_state(half_ch_r)),
277 half_ch_funcs->get_tail(half_ch_r),
278 half_ch_funcs->get_head(half_ch_r),
279 half_ch_funcs->get_fDSR(half_ch_r) ? 'D' : 'd',
280 half_ch_funcs->get_fCTS(half_ch_r) ? 'C' : 'c',
281 half_ch_funcs->get_fCD(half_ch_r) ? 'C' : 'c',
282 half_ch_funcs->get_fRI(half_ch_r) ? 'I' : 'i',
283 half_ch_funcs->get_fHEAD(half_ch_r) ? 'W' : 'w',
284 half_ch_funcs->get_fTAIL(half_ch_r) ? 'R' : 'r',
285 half_ch_funcs->get_fSTATE(half_ch_r) ? 'S' : 's',
286 half_ch_funcs->get_fBLOCKREADINTR(half_ch_r) ? 'B' : 'b',
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700287 size
Brian Swetland03e00cd2009-07-01 17:58:37 -0700288 );
289}
290
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700291static int debug_read_smsm_state(char *buf, int max)
Brian Swetland03e00cd2009-07-01 17:58:37 -0700292{
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700293 uint32_t *smsm;
294 int n, i = 0;
295
296 smsm = smem_find(ID_SHARED_STATE,
297 SMSM_NUM_ENTRIES * sizeof(uint32_t));
298
299 if (smsm)
300 for (n = 0; n < SMSM_NUM_ENTRIES; n++)
301 i += scnprintf(buf + i, max - i, "entry %d: 0x%08x\n",
302 n, smsm[n]);
303
304 return i;
305}
306
307struct SMSM_CB_DATA {
308 int cb_count;
309 void *data;
310 uint32_t old_state;
311 uint32_t new_state;
312};
313static struct SMSM_CB_DATA smsm_cb_data;
Eric Holmbergc7e8daf2011-12-28 11:49:21 -0700314static struct completion smsm_cb_completion;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700315
316static void smsm_state_cb(void *data, uint32_t old_state, uint32_t new_state)
317{
318 smsm_cb_data.cb_count++;
319 smsm_cb_data.old_state = old_state;
320 smsm_cb_data.new_state = new_state;
321 smsm_cb_data.data = data;
Eric Holmbergc7e8daf2011-12-28 11:49:21 -0700322 complete_all(&smsm_cb_completion);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700323}
324
325#define UT_EQ_INT(a, b) \
326 if ((a) != (b)) { \
327 i += scnprintf(buf + i, max - i, \
328 "%s:%d " #a "(%d) != " #b "(%d)\n", \
329 __func__, __LINE__, \
330 a, b); \
331 break; \
332 } \
333 do {} while (0)
334
Eric Holmbergc7e8daf2011-12-28 11:49:21 -0700335#define UT_GT_INT(a, b) \
336 if ((a) <= (b)) { \
337 i += scnprintf(buf + i, max - i, \
338 "%s:%d " #a "(%d) > " #b "(%d)\n", \
339 __func__, __LINE__, \
340 a, b); \
341 break; \
342 } \
343 do {} while (0)
344
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700345#define SMSM_CB_TEST_INIT() \
346 do { \
347 smsm_cb_data.cb_count = 0; \
348 smsm_cb_data.old_state = 0; \
349 smsm_cb_data.new_state = 0; \
350 smsm_cb_data.data = 0; \
351 } while (0)
352
353
354static int debug_test_smsm(char *buf, int max)
355{
Brian Swetland03e00cd2009-07-01 17:58:37 -0700356 int i = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700357 int test_num = 0;
358 int ret;
Brian Swetland03e00cd2009-07-01 17:58:37 -0700359
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700360 /* Test case 1 - Register new callback for notification */
361 do {
362 test_num++;
363 SMSM_CB_TEST_INIT();
364 ret = smsm_state_cb_register(SMSM_APPS_STATE, SMSM_SMDINIT,
365 smsm_state_cb, (void *)0x1234);
366 UT_EQ_INT(ret, 0);
Brian Swetland03e00cd2009-07-01 17:58:37 -0700367
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700368 /* de-assert SMSM_SMD_INIT to trigger state update */
369 UT_EQ_INT(smsm_cb_data.cb_count, 0);
Eric Holmbergc7e8daf2011-12-28 11:49:21 -0700370 INIT_COMPLETION(smsm_cb_completion);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700371 smsm_change_state(SMSM_APPS_STATE, SMSM_SMDINIT, 0x0);
Eric Holmbergc7e8daf2011-12-28 11:49:21 -0700372 UT_GT_INT((int)wait_for_completion_timeout(&smsm_cb_completion,
373 msecs_to_jiffies(20)), 0);
Brian Swetland03e00cd2009-07-01 17:58:37 -0700374
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700375 UT_EQ_INT(smsm_cb_data.cb_count, 1);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700376 UT_EQ_INT(smsm_cb_data.old_state & SMSM_SMDINIT, SMSM_SMDINIT);
377 UT_EQ_INT(smsm_cb_data.new_state & SMSM_SMDINIT, 0x0);
378 UT_EQ_INT((int)smsm_cb_data.data, 0x1234);
379
380 /* re-assert SMSM_SMD_INIT to trigger state update */
Eric Holmbergc7e8daf2011-12-28 11:49:21 -0700381 INIT_COMPLETION(smsm_cb_completion);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700382 smsm_change_state(SMSM_APPS_STATE, 0x0, SMSM_SMDINIT);
Eric Holmbergc7e8daf2011-12-28 11:49:21 -0700383 UT_GT_INT((int)wait_for_completion_timeout(&smsm_cb_completion,
384 msecs_to_jiffies(20)), 0);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700385 UT_EQ_INT(smsm_cb_data.cb_count, 2);
386 UT_EQ_INT(smsm_cb_data.old_state & SMSM_SMDINIT, 0x0);
387 UT_EQ_INT(smsm_cb_data.new_state & SMSM_SMDINIT, SMSM_SMDINIT);
388
389 /* deregister callback */
390 ret = smsm_state_cb_deregister(SMSM_APPS_STATE, SMSM_SMDINIT,
391 smsm_state_cb, (void *)0x1234);
392 UT_EQ_INT(ret, 2);
393
394 /* make sure state change doesn't cause any more callbacks */
Eric Holmbergc7e8daf2011-12-28 11:49:21 -0700395 INIT_COMPLETION(smsm_cb_completion);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700396 smsm_change_state(SMSM_APPS_STATE, SMSM_SMDINIT, 0x0);
397 smsm_change_state(SMSM_APPS_STATE, 0x0, SMSM_SMDINIT);
Eric Holmbergc7e8daf2011-12-28 11:49:21 -0700398 UT_EQ_INT((int)wait_for_completion_timeout(&smsm_cb_completion,
399 msecs_to_jiffies(20)), 0);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700400 UT_EQ_INT(smsm_cb_data.cb_count, 2);
401
402 i += scnprintf(buf + i, max - i, "Test %d - PASS\n", test_num);
403 } while (0);
404
405 /* Test case 2 - Update already registered callback */
406 do {
407 test_num++;
408 SMSM_CB_TEST_INIT();
409 ret = smsm_state_cb_register(SMSM_APPS_STATE, SMSM_SMDINIT,
410 smsm_state_cb, (void *)0x1234);
411 UT_EQ_INT(ret, 0);
412 ret = smsm_state_cb_register(SMSM_APPS_STATE, SMSM_INIT,
413 smsm_state_cb, (void *)0x1234);
414 UT_EQ_INT(ret, 1);
415
416 /* verify both callback bits work */
Eric Holmbergc7e8daf2011-12-28 11:49:21 -0700417 INIT_COMPLETION(smsm_cb_completion);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700418 UT_EQ_INT(smsm_cb_data.cb_count, 0);
419 smsm_change_state(SMSM_APPS_STATE, SMSM_SMDINIT, 0x0);
Eric Holmbergc7e8daf2011-12-28 11:49:21 -0700420 UT_GT_INT((int)wait_for_completion_timeout(&smsm_cb_completion,
421 msecs_to_jiffies(20)), 0);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700422 UT_EQ_INT(smsm_cb_data.cb_count, 1);
Eric Holmbergc7e8daf2011-12-28 11:49:21 -0700423 INIT_COMPLETION(smsm_cb_completion);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700424 smsm_change_state(SMSM_APPS_STATE, 0x0, SMSM_SMDINIT);
Eric Holmbergc7e8daf2011-12-28 11:49:21 -0700425 UT_GT_INT((int)wait_for_completion_timeout(&smsm_cb_completion,
426 msecs_to_jiffies(20)), 0);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700427 UT_EQ_INT(smsm_cb_data.cb_count, 2);
428
Eric Holmbergc7e8daf2011-12-28 11:49:21 -0700429 INIT_COMPLETION(smsm_cb_completion);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700430 smsm_change_state(SMSM_APPS_STATE, SMSM_INIT, 0x0);
Eric Holmbergc7e8daf2011-12-28 11:49:21 -0700431 UT_GT_INT((int)wait_for_completion_timeout(&smsm_cb_completion,
432 msecs_to_jiffies(20)), 0);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700433 UT_EQ_INT(smsm_cb_data.cb_count, 3);
Eric Holmbergc7e8daf2011-12-28 11:49:21 -0700434 INIT_COMPLETION(smsm_cb_completion);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700435 smsm_change_state(SMSM_APPS_STATE, 0x0, SMSM_INIT);
Eric Holmbergc7e8daf2011-12-28 11:49:21 -0700436 UT_GT_INT((int)wait_for_completion_timeout(&smsm_cb_completion,
437 msecs_to_jiffies(20)), 0);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700438 UT_EQ_INT(smsm_cb_data.cb_count, 4);
439
440 /* deregister 1st callback */
441 ret = smsm_state_cb_deregister(SMSM_APPS_STATE, SMSM_SMDINIT,
442 smsm_state_cb, (void *)0x1234);
443 UT_EQ_INT(ret, 1);
Eric Holmbergc7e8daf2011-12-28 11:49:21 -0700444 INIT_COMPLETION(smsm_cb_completion);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700445 smsm_change_state(SMSM_APPS_STATE, SMSM_SMDINIT, 0x0);
446 smsm_change_state(SMSM_APPS_STATE, 0x0, SMSM_SMDINIT);
Eric Holmbergc7e8daf2011-12-28 11:49:21 -0700447 UT_EQ_INT((int)wait_for_completion_timeout(&smsm_cb_completion,
448 msecs_to_jiffies(20)), 0);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700449 UT_EQ_INT(smsm_cb_data.cb_count, 4);
450
Eric Holmbergc7e8daf2011-12-28 11:49:21 -0700451 INIT_COMPLETION(smsm_cb_completion);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700452 smsm_change_state(SMSM_APPS_STATE, SMSM_INIT, 0x0);
Eric Holmbergc7e8daf2011-12-28 11:49:21 -0700453 UT_GT_INT((int)wait_for_completion_timeout(&smsm_cb_completion,
454 msecs_to_jiffies(20)), 0);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700455 UT_EQ_INT(smsm_cb_data.cb_count, 5);
Eric Holmbergc7e8daf2011-12-28 11:49:21 -0700456 INIT_COMPLETION(smsm_cb_completion);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700457 smsm_change_state(SMSM_APPS_STATE, 0x0, SMSM_INIT);
Eric Holmbergc7e8daf2011-12-28 11:49:21 -0700458 UT_GT_INT((int)wait_for_completion_timeout(&smsm_cb_completion,
459 msecs_to_jiffies(20)), 0);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700460 UT_EQ_INT(smsm_cb_data.cb_count, 6);
461
462 /* deregister 2nd callback */
463 ret = smsm_state_cb_deregister(SMSM_APPS_STATE, SMSM_INIT,
464 smsm_state_cb, (void *)0x1234);
465 UT_EQ_INT(ret, 2);
466
467 /* make sure state change doesn't cause any more callbacks */
Eric Holmbergc7e8daf2011-12-28 11:49:21 -0700468 INIT_COMPLETION(smsm_cb_completion);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700469 smsm_change_state(SMSM_APPS_STATE, SMSM_INIT, 0x0);
470 smsm_change_state(SMSM_APPS_STATE, 0x0, SMSM_INIT);
Eric Holmbergc7e8daf2011-12-28 11:49:21 -0700471 UT_EQ_INT((int)wait_for_completion_timeout(&smsm_cb_completion,
472 msecs_to_jiffies(20)), 0);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700473 UT_EQ_INT(smsm_cb_data.cb_count, 6);
474
475 i += scnprintf(buf + i, max - i, "Test %d - PASS\n", test_num);
476 } while (0);
477
478 /* Test case 3 - Two callback registrations with different data */
479 do {
480 test_num++;
481 SMSM_CB_TEST_INIT();
482 ret = smsm_state_cb_register(SMSM_APPS_STATE, SMSM_SMDINIT,
483 smsm_state_cb, (void *)0x1234);
484 UT_EQ_INT(ret, 0);
485 ret = smsm_state_cb_register(SMSM_APPS_STATE, SMSM_INIT,
486 smsm_state_cb, (void *)0x3456);
487 UT_EQ_INT(ret, 0);
488
489 /* verify both callbacks work */
Eric Holmbergc7e8daf2011-12-28 11:49:21 -0700490 INIT_COMPLETION(smsm_cb_completion);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700491 UT_EQ_INT(smsm_cb_data.cb_count, 0);
492 smsm_change_state(SMSM_APPS_STATE, SMSM_SMDINIT, 0x0);
Eric Holmbergc7e8daf2011-12-28 11:49:21 -0700493 UT_GT_INT((int)wait_for_completion_timeout(&smsm_cb_completion,
494 msecs_to_jiffies(20)), 0);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700495 UT_EQ_INT(smsm_cb_data.cb_count, 1);
496 UT_EQ_INT((int)smsm_cb_data.data, 0x1234);
497
Eric Holmbergc7e8daf2011-12-28 11:49:21 -0700498 INIT_COMPLETION(smsm_cb_completion);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700499 smsm_change_state(SMSM_APPS_STATE, SMSM_INIT, 0x0);
Eric Holmbergc7e8daf2011-12-28 11:49:21 -0700500 UT_GT_INT((int)wait_for_completion_timeout(&smsm_cb_completion,
501 msecs_to_jiffies(20)), 0);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700502 UT_EQ_INT(smsm_cb_data.cb_count, 2);
503 UT_EQ_INT((int)smsm_cb_data.data, 0x3456);
504
505 /* cleanup and unregister
506 * degregister in reverse to verify data field is
507 * being used
508 */
509 smsm_change_state(SMSM_APPS_STATE, 0x0, SMSM_SMDINIT);
510 smsm_change_state(SMSM_APPS_STATE, 0x0, SMSM_INIT);
511 ret = smsm_state_cb_deregister(SMSM_APPS_STATE,
512 SMSM_INIT,
513 smsm_state_cb, (void *)0x3456);
514 UT_EQ_INT(ret, 2);
515 ret = smsm_state_cb_deregister(SMSM_APPS_STATE,
516 SMSM_SMDINIT,
517 smsm_state_cb, (void *)0x1234);
518 UT_EQ_INT(ret, 2);
519
520 i += scnprintf(buf + i, max - i, "Test %d - PASS\n", test_num);
521 } while (0);
522
Brian Swetland03e00cd2009-07-01 17:58:37 -0700523 return i;
524}
525
526static int debug_read_mem(char *buf, int max)
527{
528 unsigned n;
529 struct smem_shared *shared = (void *) MSM_SHARED_RAM_BASE;
530 struct smem_heap_entry *toc = shared->heap_toc;
531 int i = 0;
532
533 i += scnprintf(buf + i, max - i,
534 "heap: init=%d free=%d remain=%d\n",
535 shared->heap_info.initialized,
536 shared->heap_info.free_offset,
537 shared->heap_info.heap_remaining);
538
539 for (n = 0; n < SMEM_NUM_ITEMS; n++) {
540 if (toc[n].allocated == 0)
541 continue;
542 i += scnprintf(buf + i, max - i,
543 "%04d: offset %08x size %08x\n",
544 n, toc[n].offset, toc[n].size);
545 }
546 return i;
547}
548
Eric Holmberg27134822011-12-15 16:07:50 -0700549#if (!defined(CONFIG_MSM_SMD_PKG4) && !defined(CONFIG_MSM_SMD_PKG3))
Brian Swetland03e00cd2009-07-01 17:58:37 -0700550static int debug_read_ch(char *buf, int max)
551{
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700552 void *shared;
553 int n, i = 0;
Jeff Hugo918b2dc2012-03-21 13:42:09 -0600554 struct smd_alloc_elm *ch_tbl;
555 unsigned ch_type;
556 unsigned shared_size;
Brian Swetland03e00cd2009-07-01 17:58:37 -0700557
Jeff Hugo918b2dc2012-03-21 13:42:09 -0600558 ch_tbl = smem_find(ID_CH_ALLOC_TBL, sizeof(*ch_tbl) * 64);
559 if (!ch_tbl)
560 goto fail;
Brian Swetland03e00cd2009-07-01 17:58:37 -0700561
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700562 for (n = 0; n < SMD_CHANNELS; n++) {
Jeff Hugo918b2dc2012-03-21 13:42:09 -0600563 ch_type = SMD_CHANNEL_TYPE(ch_tbl[n].type);
564 if (is_word_access_ch(ch_type))
565 shared_size =
566 sizeof(struct smd_half_channel_word_access);
567 else
568 shared_size = sizeof(struct smd_half_channel);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700569 shared = smem_find(ID_SMD_CHANNELS + n,
Jeff Hugo918b2dc2012-03-21 13:42:09 -0600570 2 * shared_size + SMD_BUF_SIZE);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700571
572 if (shared == 0)
573 continue;
574 i += dump_ch(buf + i, max - i, n, shared,
Jeff Hugo918b2dc2012-03-21 13:42:09 -0600575 (shared + shared_size +
576 SMD_BUF_SIZE), get_half_ch_funcs(ch_type),
577 SMD_BUF_SIZE);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700578 }
Brian Swetland03e00cd2009-07-01 17:58:37 -0700579
Jeff Hugo918b2dc2012-03-21 13:42:09 -0600580fail:
Brian Swetland03e00cd2009-07-01 17:58:37 -0700581 return i;
582}
Eric Holmberg27134822011-12-15 16:07:50 -0700583#else
584static int debug_read_ch(char *buf, int max)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700585{
586 void *shared, *buffer;
587 unsigned buffer_sz;
588 int n, i = 0;
Jeff Hugo918b2dc2012-03-21 13:42:09 -0600589 struct smd_alloc_elm *ch_tbl;
590 unsigned ch_type;
591 unsigned shared_size;
592
593 ch_tbl = smem_find(ID_CH_ALLOC_TBL, sizeof(*ch_tbl) * 64);
594 if (!ch_tbl)
595 goto fail;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700596
597 for (n = 0; n < SMD_CHANNELS; n++) {
Jeff Hugo918b2dc2012-03-21 13:42:09 -0600598 ch_type = SMD_CHANNEL_TYPE(ch_tbl[n].type);
599 if (is_word_access_ch(ch_type))
600 shared_size =
601 sizeof(struct smd_half_channel_word_access);
602 else
603 shared_size = sizeof(struct smd_half_channel);
604
605 shared = smem_find(ID_SMD_CHANNELS + n, 2 * shared_size);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700606
607 if (shared == 0)
608 continue;
609
610 buffer = smem_get_entry(SMEM_SMD_FIFO_BASE_ID + n, &buffer_sz);
611
612 if (buffer == 0)
613 continue;
614
615 i += dump_ch(buf + i, max - i, n, shared,
Jeff Hugo918b2dc2012-03-21 13:42:09 -0600616 (shared + shared_size),
617 get_half_ch_funcs(ch_type),
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700618 buffer_sz / 2);
619 }
620
Jeff Hugo918b2dc2012-03-21 13:42:09 -0600621fail:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700622 return i;
623}
Eric Holmberg27134822011-12-15 16:07:50 -0700624#endif
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700625
626static int debug_read_smem_version(char *buf, int max)
Brian Swetland03e00cd2009-07-01 17:58:37 -0700627{
628 struct smem_shared *shared = (void *) MSM_SHARED_RAM_BASE;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700629 uint32_t n, version, i = 0;
630
631 for (n = 0; n < 32; n++) {
632 version = shared->version[n];
633 i += scnprintf(buf + i, max - i,
634 "entry %d: smem = %d proc_comm = %d\n", n,
635 version >> 16,
636 version & 0xffff);
637 }
Brian Swetland03e00cd2009-07-01 17:58:37 -0700638
639 return i;
640}
641
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700642/* NNV: revist, it may not be smd version */
643static int debug_read_smd_version(char *buf, int max)
Brian Swetland03e00cd2009-07-01 17:58:37 -0700644{
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700645 uint32_t *smd_ver;
646 uint32_t n, version, i = 0;
647
648 smd_ver = smem_alloc(SMEM_VERSION_SMD, 32 * sizeof(uint32_t));
649
650 if (smd_ver)
651 for (n = 0; n < 32; n++) {
652 version = smd_ver[n];
653 i += scnprintf(buf + i, max - i,
654 "entry %d: %d.%d\n", n,
655 version >> 16,
656 version & 0xffff);
657 }
658
659 return i;
Brian Swetland03e00cd2009-07-01 17:58:37 -0700660}
661
662static int debug_read_build_id(char *buf, int max)
663{
664 unsigned size;
665 void *data;
666
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700667 data = smem_get_entry(SMEM_HW_SW_BUILD_ID, &size);
Brian Swetland03e00cd2009-07-01 17:58:37 -0700668 if (!data)
669 return 0;
670
671 if (size >= max)
672 size = max;
673 memcpy(buf, data, size);
674
675 return size;
676}
677
678static int debug_read_alloc_tbl(char *buf, int max)
679{
680 struct smd_alloc_elm *shared;
681 int n, i = 0;
682
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700683 shared = smem_find(ID_CH_ALLOC_TBL, sizeof(struct smd_alloc_elm[64]));
684
685 if (!shared)
686 return 0;
Brian Swetland03e00cd2009-07-01 17:58:37 -0700687
688 for (n = 0; n < 64; n++) {
Brian Swetland03e00cd2009-07-01 17:58:37 -0700689 i += scnprintf(buf + i, max - i,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700690 "name=%s cid=%d ch type=%d "
691 "xfer type=%d ref_count=%d\n",
692 shared[n].name,
693 shared[n].cid,
694 SMD_CHANNEL_TYPE(shared[n].type),
695 SMD_XFER_TYPE(shared[n].type),
696 shared[n].ref_count);
Brian Swetland03e00cd2009-07-01 17:58:37 -0700697 }
698
699 return i;
700}
701
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700702static int debug_read_intr_mask(char *buf, int max)
703{
704 uint32_t *smsm;
705 int m, n, i = 0;
706
707 smsm = smem_alloc(SMEM_SMSM_CPU_INTR_MASK,
708 SMSM_NUM_ENTRIES * SMSM_NUM_HOSTS * sizeof(uint32_t));
709
710 if (smsm)
711 for (m = 0; m < SMSM_NUM_ENTRIES; m++) {
712 i += scnprintf(buf + i, max - i, "entry %d:", m);
713 for (n = 0; n < SMSM_NUM_HOSTS; n++)
714 i += scnprintf(buf + i, max - i,
715 " host %d: 0x%08x",
716 n, smsm[m * SMSM_NUM_HOSTS + n]);
717 i += scnprintf(buf + i, max - i, "\n");
718 }
719
720 return i;
721}
722
723static int debug_read_intr_mux(char *buf, int max)
724{
725 uint32_t *smsm;
726 int n, i = 0;
727
728 smsm = smem_alloc(SMEM_SMD_SMSM_INTR_MUX,
729 SMSM_NUM_INTR_MUX * sizeof(uint32_t));
730
731 if (smsm)
732 for (n = 0; n < SMSM_NUM_INTR_MUX; n++)
733 i += scnprintf(buf + i, max - i, "entry %d: %d\n",
734 n, smsm[n]);
735
736 return i;
737}
738
Brian Swetland03e00cd2009-07-01 17:58:37 -0700739#define DEBUG_BUFMAX 4096
740static char debug_buffer[DEBUG_BUFMAX];
741
742static ssize_t debug_read(struct file *file, char __user *buf,
743 size_t count, loff_t *ppos)
744{
745 int (*fill)(char *buf, int max) = file->private_data;
Eric Holmbergf9a75f52011-12-28 19:04:18 -0700746 int bsize;
747
748 if (*ppos != 0)
749 return 0;
750
751 bsize = fill(debug_buffer, DEBUG_BUFMAX);
Brian Swetland03e00cd2009-07-01 17:58:37 -0700752 return simple_read_from_buffer(buf, count, ppos, debug_buffer, bsize);
753}
754
Brian Swetland03e00cd2009-07-01 17:58:37 -0700755static const struct file_operations debug_ops = {
756 .read = debug_read,
Stephen Boyd234e3402012-04-05 14:25:11 -0700757 .open = simple_open,
Brian Swetland03e00cd2009-07-01 17:58:37 -0700758};
759
Al Virof4ae40a2011-07-24 04:33:43 -0400760static void debug_create(const char *name, umode_t mode,
Brian Swetland03e00cd2009-07-01 17:58:37 -0700761 struct dentry *dent,
762 int (*fill)(char *buf, int max))
763{
764 debugfs_create_file(name, mode, dent, fill, &debug_ops);
765}
766
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700767static int __init smd_debugfs_init(void)
Brian Swetland03e00cd2009-07-01 17:58:37 -0700768{
769 struct dentry *dent;
770
771 dent = debugfs_create_dir("smd", 0);
772 if (IS_ERR(dent))
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700773 return PTR_ERR(dent);
Brian Swetland03e00cd2009-07-01 17:58:37 -0700774
775 debug_create("ch", 0444, dent, debug_read_ch);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700776 debug_create("diag", 0444, dent, debug_read_diag_msg);
Brian Swetland03e00cd2009-07-01 17:58:37 -0700777 debug_create("mem", 0444, dent, debug_read_mem);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700778 debug_create("version", 0444, dent, debug_read_smd_version);
Brian Swetland03e00cd2009-07-01 17:58:37 -0700779 debug_create("tbl", 0444, dent, debug_read_alloc_tbl);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700780 debug_create("modem_err", 0444, dent, debug_modem_err);
781 debug_create("modem_err_f3", 0444, dent, debug_modem_err_f3);
782 debug_create("print_diag", 0444, dent, debug_diag);
783 debug_create("print_f3", 0444, dent, debug_f3);
Eric Holmberg7ad623a2012-03-01 14:41:10 -0700784 debug_create("int_stats", 0444, dent, debug_int_stats);
785 debug_create("int_stats_reset", 0444, dent, debug_int_stats_reset);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700786
787 /* NNV: this is google only stuff */
Brian Swetland03e00cd2009-07-01 17:58:37 -0700788 debug_create("build", 0444, dent, debug_read_build_id);
Daniel Walker869a2a02010-04-23 11:04:14 -0700789
790 return 0;
Brian Swetland03e00cd2009-07-01 17:58:37 -0700791}
792
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700793static int __init smsm_debugfs_init(void)
794{
795 struct dentry *dent;
796
797 dent = debugfs_create_dir("smsm", 0);
798 if (IS_ERR(dent))
799 return PTR_ERR(dent);
800
801 debug_create("state", 0444, dent, debug_read_smsm_state);
802 debug_create("intr_mask", 0444, dent, debug_read_intr_mask);
803 debug_create("intr_mux", 0444, dent, debug_read_intr_mux);
804 debug_create("version", 0444, dent, debug_read_smem_version);
805 debug_create("smsm_test", 0444, dent, debug_test_smsm);
806
Eric Holmbergc7e8daf2011-12-28 11:49:21 -0700807 init_completion(&smsm_cb_completion);
808
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700809 return 0;
810}
811
Brian Swetland03e00cd2009-07-01 17:58:37 -0700812late_initcall(smd_debugfs_init);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700813late_initcall(smsm_debugfs_init);
Brian Swetland03e00cd2009-07-01 17:58:37 -0700814#endif
815
816
817#define MAX_NUM_SLEEP_CLIENTS 64
818#define MAX_SLEEP_NAME_LEN 8
819
820#define NUM_GPIO_INT_REGISTERS 6
821#define GPIO_SMEM_NUM_GROUPS 2
822#define GPIO_SMEM_MAX_PC_INTERRUPTS 8
823
824struct tramp_gpio_save {
825 unsigned int enable;
826 unsigned int detect;
827 unsigned int polarity;
828};
829
830struct tramp_gpio_smem {
831 uint16_t num_fired[GPIO_SMEM_NUM_GROUPS];
832 uint16_t fired[GPIO_SMEM_NUM_GROUPS][GPIO_SMEM_MAX_PC_INTERRUPTS];
833 uint32_t enabled[NUM_GPIO_INT_REGISTERS];
834 uint32_t detection[NUM_GPIO_INT_REGISTERS];
835 uint32_t polarity[NUM_GPIO_INT_REGISTERS];
836};
837
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700838/*
839 * Print debug information on shared memory sleep variables
840 */
841void smsm_print_sleep_info(uint32_t sleep_delay, uint32_t sleep_limit,
842 uint32_t irq_mask, uint32_t wakeup_reason, uint32_t pending_irqs)
Brian Swetland03e00cd2009-07-01 17:58:37 -0700843{
844 unsigned long flags;
845 uint32_t *ptr;
846 struct tramp_gpio_smem *gpio;
Brian Swetland03e00cd2009-07-01 17:58:37 -0700847
848 spin_lock_irqsave(&smem_lock, flags);
849
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700850 pr_info("SMEM_SMSM_SLEEP_DELAY: %x\n", sleep_delay);
851 pr_info("SMEM_SMSM_LIMIT_SLEEP: %x\n", sleep_limit);
Brian Swetland03e00cd2009-07-01 17:58:37 -0700852
853 ptr = smem_alloc(SMEM_SLEEP_POWER_COLLAPSE_DISABLED, sizeof(*ptr));
854 if (ptr)
855 pr_info("SMEM_SLEEP_POWER_COLLAPSE_DISABLED: %x\n", *ptr);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700856 else
857 pr_info("SMEM_SLEEP_POWER_COLLAPSE_DISABLED: missing\n");
Brian Swetland03e00cd2009-07-01 17:58:37 -0700858
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700859 pr_info("SMEM_SMSM_INT_INFO %x %x %x\n",
860 irq_mask, pending_irqs, wakeup_reason);
Brian Swetland03e00cd2009-07-01 17:58:37 -0700861
862 gpio = smem_alloc(SMEM_GPIO_INT, sizeof(*gpio));
863 if (gpio) {
864 int i;
865 for (i = 0; i < NUM_GPIO_INT_REGISTERS; i++)
866 pr_info("SMEM_GPIO_INT: %d: e %x d %x p %x\n",
867 i, gpio->enabled[i], gpio->detection[i],
868 gpio->polarity[i]);
869
870 for (i = 0; i < GPIO_SMEM_NUM_GROUPS; i++)
871 pr_info("SMEM_GPIO_INT: %d: f %d: %d %d...\n",
872 i, gpio->num_fired[i], gpio->fired[i][0],
873 gpio->fired[i][1]);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700874 } else
875 pr_info("SMEM_GPIO_INT: missing\n");
876
Brian Swetland03e00cd2009-07-01 17:58:37 -0700877 spin_unlock_irqrestore(&smem_lock, flags);
878}