2016-09-28 00:29:55 +08:00
|
|
|
/*
|
|
|
|
* mbox dump to debug log convertor.
|
|
|
|
*
|
|
|
|
* Copyright (c) 2015, Intel Corporation.
|
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or modify it
|
|
|
|
* under the terms and conditions of the GNU General Public License,
|
|
|
|
* version 2, as published by the Free Software Foundation.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope it will be useful, but WITHOUT
|
|
|
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
|
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
|
|
|
* more details.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
#include <stdint.h>
|
|
|
|
#include <errno.h>
|
|
|
|
#include <string.h>
|
|
|
|
|
|
|
|
// TODO: include all this stuff
|
|
|
|
|
|
|
|
#define TRACE_CLASS_IRQ (1 << 24)
|
|
|
|
#define TRACE_CLASS_IPC (2 << 24)
|
|
|
|
#define TRACE_CLASS_PIPE (3 << 24)
|
|
|
|
#define TRACE_CLASS_HOST (4 << 24)
|
|
|
|
#define TRACE_CLASS_DAI (5 << 24)
|
|
|
|
#define TRACE_CLASS_DMA (6 << 24)
|
|
|
|
#define TRACE_CLASS_SSP (7 << 24)
|
|
|
|
#define TRACE_CLASS_COMP (8 << 24)
|
|
|
|
#define TRACE_CLASS_WAIT (9 << 24)
|
|
|
|
#define TRACE_CLASS_LOCK (10 << 24)
|
|
|
|
#define TRACE_CLASS_MEM (11 << 24)
|
|
|
|
#define TRACE_CLASS_MIXER (12 << 24)
|
2017-06-09 21:36:33 +08:00
|
|
|
#define TRACE_CLASS_BUFFER (13 << 24)
|
|
|
|
#define TRACE_CLASS_VOLUME (14 << 24)
|
|
|
|
#define TRACE_CLASS_SWITCH (15 << 24)
|
|
|
|
#define TRACE_CLASS_MUX (16 << 24)
|
2017-08-25 00:10:49 +08:00
|
|
|
#define TRACE_CLASS_SRC (17 << 24)
|
|
|
|
#define TRACE_CLASS_TONE (18 << 24)
|
|
|
|
#define TRACE_CLASS_EQ_FIR (19 << 24)
|
|
|
|
#define TRACE_CLASS_EQ_IIR (20 << 24)
|
2016-09-28 00:29:55 +08:00
|
|
|
|
|
|
|
#define MAILBOX_HOST_OFFSET 0x144000
|
|
|
|
|
|
|
|
#define MAILBOX_OUTBOX_OFFSET 0x0
|
|
|
|
#define MAILBOX_OUTBOX_SIZE 0x400
|
|
|
|
#define MAILBOX_OUTBOX_BASE \
|
|
|
|
(MAILBOX_BASE + MAILBOX_OUTBOX_OFFSET)
|
|
|
|
|
|
|
|
#define MAILBOX_INBOX_OFFSET MAILBOX_OUTBOX_SIZE
|
|
|
|
#define MAILBOX_INBOX_SIZE 0x400
|
|
|
|
#define MAILBOX_INBOX_BASE \
|
|
|
|
(MAILBOX_BASE + MAILBOX_INBOX_OFFSET)
|
|
|
|
|
|
|
|
#define MAILBOX_EXCEPTION_OFFSET \
|
|
|
|
(MAILBOX_INBOX_SIZE + MAILBOX_OUTBOX_SIZE)
|
|
|
|
#define MAILBOX_EXCEPTION_SIZE 0x100
|
|
|
|
#define MAILBOX_EXCEPTION_BASE \
|
|
|
|
(MAILBOX_BASE + MAILBOX_EXCEPTION_OFFSET)
|
|
|
|
|
|
|
|
#define MAILBOX_DEBUG_OFFSET \
|
|
|
|
(MAILBOX_EXCEPTION_SIZE + MAILBOX_EXCEPTION_OFFSET)
|
|
|
|
#define MAILBOX_DEBUG_SIZE 0x100
|
|
|
|
#define MAILBOX_DEBUG_BASE \
|
|
|
|
(MAILBOX_BASE + MAILBOX_DEBUG_OFFSET)
|
|
|
|
|
|
|
|
#define MAILBOX_STREAM_OFFSET \
|
|
|
|
(MAILBOX_DEBUG_SIZE + MAILBOX_DEBUG_OFFSET)
|
|
|
|
#define MAILBOX_STREAM_SIZE 0x200
|
|
|
|
#define MAILBOX_STREAM_BASE \
|
|
|
|
(MAILBOX_BASE + MAILBOX_STREAM_OFFSET)
|
|
|
|
|
|
|
|
#define MAILBOX_TRACE_OFFSET \
|
|
|
|
(MAILBOX_STREAM_SIZE + MAILBOX_STREAM_OFFSET)
|
|
|
|
#define MAILBOX_TRACE_SIZE 0x380
|
|
|
|
#define MAILBOX_TRACE_BASE \
|
|
|
|
(MAILBOX_BASE + MAILBOX_TRACE_OFFSET)
|
|
|
|
|
|
|
|
#define ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0]))
|
|
|
|
|
|
|
|
static inline char get_char(uint32_t val, int idx)
|
|
|
|
{
|
|
|
|
char c = (val >> (idx * 8)) & 0xff;
|
|
|
|
if (c < '0' || c > 'z')
|
|
|
|
return '.';
|
|
|
|
else
|
|
|
|
return c;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void usage(char *name)
|
|
|
|
{
|
2017-08-31 05:24:03 +08:00
|
|
|
fprintf(stdout, "Usage %s <option(s)> <file(s)>\n", name);
|
|
|
|
fprintf(stdout, "%s:\t -i infile -o outfile\tDump infile contents to outfile\n", name);
|
|
|
|
fprintf(stdout, "%s:\t -c\t\t\tSet timestamp clock in MHz\n", name);
|
|
|
|
fprintf(stdout, "%s:\t -s\t\t\tTake a snapshot of state\n", name);
|
2016-09-28 00:29:55 +08:00
|
|
|
exit(0);
|
|
|
|
}
|
|
|
|
|
2017-08-31 05:24:54 +08:00
|
|
|
static float to_usecs(uint32_t time, float clk)
|
2016-09-28 00:29:55 +08:00
|
|
|
{
|
2017-06-09 21:55:36 +08:00
|
|
|
/* trace timestamp uses CPU system clock at default 25MHz ticks */
|
2016-09-28 00:29:55 +08:00
|
|
|
// TODO: support variable clock rates
|
2017-06-09 21:55:36 +08:00
|
|
|
return (float)time / clk;
|
2016-09-28 00:29:55 +08:00
|
|
|
}
|
|
|
|
|
2017-08-31 05:24:54 +08:00
|
|
|
static void show_trace(uint32_t val, uint32_t addr, uint32_t *timestamp, float clk)
|
2016-09-28 00:29:55 +08:00
|
|
|
{
|
|
|
|
const char *trace;
|
|
|
|
uint32_t class;
|
2017-08-31 05:24:54 +08:00
|
|
|
uint32_t delta = val - *timestamp;
|
|
|
|
float fdelta = to_usecs(delta, clk);
|
2016-09-28 00:29:55 +08:00
|
|
|
|
|
|
|
/* timestamp or value ? */
|
|
|
|
if ((addr % 8) == 0) {
|
2017-08-31 05:24:54 +08:00
|
|
|
|
|
|
|
/* buffer wrap ? */
|
|
|
|
if (val < *timestamp) {
|
|
|
|
printf("----------------------------------------"
|
|
|
|
"----------------------------------------"
|
|
|
|
"--------------------------------------\n");
|
|
|
|
delta = 0;
|
|
|
|
fdelta = 0.0;
|
|
|
|
} else {
|
|
|
|
delta = val - *timestamp;
|
|
|
|
fdelta = to_usecs(delta, clk);
|
|
|
|
}
|
|
|
|
|
2016-09-28 00:29:55 +08:00
|
|
|
printf("trace.io: timestamp 0x%8.8x (%2.2f us) \tdelta 0x%8.8x (%2.2f us)\t",
|
2017-06-09 21:55:36 +08:00
|
|
|
(uint32_t)val, to_usecs(val, clk),
|
2017-08-31 05:24:54 +08:00
|
|
|
(uint32_t)delta, fdelta);
|
2016-09-28 00:29:55 +08:00
|
|
|
*timestamp = val;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
class = val & 0xff000000;
|
|
|
|
if (class == TRACE_CLASS_IRQ)
|
|
|
|
trace = "irq";
|
|
|
|
else if (class == TRACE_CLASS_IPC)
|
|
|
|
trace = "ipc";
|
|
|
|
else if (class == TRACE_CLASS_PIPE)
|
|
|
|
trace = "pipe";
|
|
|
|
else if (class == TRACE_CLASS_HOST)
|
|
|
|
trace = "host";
|
|
|
|
else if (class == TRACE_CLASS_DAI)
|
|
|
|
trace = "dai";
|
|
|
|
else if (class == TRACE_CLASS_DMA)
|
|
|
|
trace = "dma";
|
|
|
|
else if (class == TRACE_CLASS_SSP)
|
|
|
|
trace = "ssp";
|
|
|
|
else if (class == TRACE_CLASS_COMP)
|
|
|
|
trace = "comp";
|
|
|
|
else if (class == TRACE_CLASS_WAIT)
|
|
|
|
trace = "wait";
|
|
|
|
else if (class == TRACE_CLASS_LOCK)
|
|
|
|
trace = "lock";
|
|
|
|
else if (class == TRACE_CLASS_MEM)
|
|
|
|
trace = "mem";
|
|
|
|
else if (class == TRACE_CLASS_MIXER)
|
|
|
|
trace = "mixer";
|
2017-06-09 21:36:33 +08:00
|
|
|
else if (class == TRACE_CLASS_BUFFER)
|
|
|
|
trace = "buffer";
|
|
|
|
else if (class == TRACE_CLASS_VOLUME)
|
|
|
|
trace = "volume";
|
|
|
|
else if (class == TRACE_CLASS_SWITCH)
|
|
|
|
trace = "switch";
|
|
|
|
else if (class == TRACE_CLASS_MUX)
|
|
|
|
trace = "mux";
|
2017-08-25 00:10:49 +08:00
|
|
|
else if (class == TRACE_CLASS_SRC)
|
|
|
|
trace = "src";
|
|
|
|
else if (class == TRACE_CLASS_TONE)
|
|
|
|
trace = "tone";
|
|
|
|
else if (class == TRACE_CLASS_EQ_FIR)
|
|
|
|
trace = "eq-fir";
|
|
|
|
else if (class == TRACE_CLASS_EQ_IIR)
|
|
|
|
trace = "eq-iir";
|
2016-09-28 00:29:55 +08:00
|
|
|
else {
|
|
|
|
printf("value 0x%8.8x\n", (uint32_t)val);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
printf("%s %c%c%c\n", trace,
|
|
|
|
(char)(val >> 16), (char)(val >> 8), (char)val);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void show_debug(uint32_t val, uint32_t addr)
|
|
|
|
{
|
|
|
|
printf("debug: 0x%x (%2.2d) = \t0x%8.8x \t(%8.8d) \t|%c%c%c%c|\n",
|
|
|
|
(unsigned int)addr - MAILBOX_DEBUG_OFFSET,
|
|
|
|
((unsigned int)addr - MAILBOX_DEBUG_OFFSET) / 4,
|
|
|
|
val, val,
|
|
|
|
get_char(val, 3), get_char(val, 2),
|
|
|
|
get_char(val, 1), get_char(val, 0));
|
|
|
|
}
|
|
|
|
|
|
|
|
static void show_exception(uint32_t val, uint32_t addr)
|
|
|
|
{
|
|
|
|
printf("exp: 0x%x (%2.2d) = \t0x%8.8x \t(%8.8d) \t|%c%c%c%c|\n",
|
|
|
|
(unsigned int)addr - MAILBOX_EXCEPTION_OFFSET,
|
|
|
|
((unsigned int)addr - MAILBOX_EXCEPTION_OFFSET) / 4,
|
|
|
|
val, val,
|
|
|
|
get_char(val, 3), get_char(val, 2),
|
|
|
|
get_char(val, 1), get_char(val, 0));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-02-28 19:51:55 +08:00
|
|
|
static const char *debugfs[] = {
|
|
|
|
"dmac0","dmac1", "ssp0", "ssp1", "ssp2", "iram", "dram", "shim", "mbox"
|
2016-09-28 00:29:55 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
static int snapshot(const char *name)
|
|
|
|
{
|
|
|
|
const char *path = "/sys/kernel/debug";
|
|
|
|
uint32_t val, addr;
|
|
|
|
char pinname[64], poutname[64], buffer[128];
|
|
|
|
FILE *in_fd, *out_fd;
|
|
|
|
int i, count;
|
|
|
|
|
2017-02-28 19:51:55 +08:00
|
|
|
if (name == NULL) {
|
|
|
|
fprintf(stderr, "error: need snapshot name\n");
|
2016-09-28 00:29:55 +08:00
|
|
|
return -EINVAL;
|
2017-02-28 19:51:55 +08:00
|
|
|
}
|
2016-09-28 00:29:55 +08:00
|
|
|
|
2017-02-28 19:51:55 +08:00
|
|
|
for (i = 0; i < ARRAY_SIZE(debugfs); i++) {
|
2016-09-28 00:29:55 +08:00
|
|
|
|
2017-02-28 19:51:55 +08:00
|
|
|
sprintf(pinname, "%s/%s", path, debugfs[i]);
|
|
|
|
sprintf(poutname, "%s.%s.txt", name, debugfs[i]);
|
2016-09-28 00:29:55 +08:00
|
|
|
|
|
|
|
/* open debugfs for reading */
|
|
|
|
in_fd = fopen(pinname, "r");
|
|
|
|
if (in_fd == NULL) {
|
|
|
|
fprintf(stderr, "error: unable to open %s for reading %d\n",
|
|
|
|
pinname, errno);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* open outfile for reading */
|
|
|
|
out_fd = fopen(poutname, "w");
|
|
|
|
if (out_fd == NULL) {
|
|
|
|
fprintf(stderr, "error: unable to open %s for writing %d\n",
|
|
|
|
poutname, errno);
|
|
|
|
fclose(in_fd);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
fprintf(stdout, "processing %s...\n", pinname);
|
|
|
|
addr = 0;
|
|
|
|
|
|
|
|
while (1) {
|
|
|
|
count = fread(&val, 1, 4, in_fd);
|
|
|
|
if (count != 4)
|
|
|
|
break;
|
|
|
|
|
|
|
|
sprintf(buffer, "0x%6.6x: 0x%8.8x\n", addr, val);
|
|
|
|
|
|
|
|
count = fwrite(buffer, 1, strlen(buffer), out_fd);
|
|
|
|
|
|
|
|
addr += 4;
|
|
|
|
}
|
|
|
|
|
2017-06-15 21:36:24 +08:00
|
|
|
fclose(in_fd);
|
|
|
|
fclose(out_fd);
|
2016-09-28 00:29:55 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int main(int argc, char *argv[])
|
|
|
|
{
|
|
|
|
int opt, count;
|
2017-06-09 21:55:36 +08:00
|
|
|
const char * out_file = NULL, *in_file = "/sys/kernel/debug/sof/mbox";
|
2017-02-28 19:51:55 +08:00
|
|
|
FILE *in_fd = NULL, *out_fd = NULL;
|
2016-09-28 00:29:55 +08:00
|
|
|
char c, tmp[4] = {0};
|
2017-08-31 05:24:54 +08:00
|
|
|
uint32_t addr = 0, val, timestamp = 0;
|
|
|
|
float clk = 19.2f;
|
2016-09-28 00:29:55 +08:00
|
|
|
|
2017-06-09 21:55:36 +08:00
|
|
|
while ((opt = getopt(argc, argv, "ho:i:s:m:c:")) != -1) {
|
2016-09-28 00:29:55 +08:00
|
|
|
switch (opt) {
|
|
|
|
case 'o':
|
|
|
|
out_file = optarg;
|
|
|
|
break;
|
|
|
|
case 'i':
|
|
|
|
in_file = optarg;
|
|
|
|
break;
|
2017-06-09 21:55:36 +08:00
|
|
|
case 'c':
|
2017-08-31 05:24:54 +08:00
|
|
|
clk = atof(optarg);
|
2017-06-09 21:55:36 +08:00
|
|
|
break;
|
2016-09-28 00:29:55 +08:00
|
|
|
case 's':
|
|
|
|
return snapshot(optarg);
|
|
|
|
case 'h':
|
|
|
|
default: /* '?' */
|
|
|
|
usage(argv[0]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* open infile for reading */
|
|
|
|
in_fd = fopen(in_file, "r");
|
|
|
|
if (in_fd == NULL) {
|
|
|
|
fprintf(stderr, "error: unable to open %s for reading %d\n",
|
|
|
|
in_file, errno);
|
2017-06-09 21:37:14 +08:00
|
|
|
return -EIO;
|
2016-09-28 00:29:55 +08:00
|
|
|
}
|
|
|
|
|
2017-02-28 19:51:55 +08:00
|
|
|
/* open outfile for writing */
|
|
|
|
if (out_file == NULL)
|
|
|
|
goto convert;
|
|
|
|
|
2016-09-28 00:29:55 +08:00
|
|
|
out_fd = fopen(out_file, "w");
|
|
|
|
if (out_fd == NULL) {
|
|
|
|
fprintf(stderr, "error: unable to open %s for writing %d\n",
|
|
|
|
out_file, errno);
|
2017-06-15 21:36:24 +08:00
|
|
|
fclose(in_fd);
|
2017-06-09 21:37:14 +08:00
|
|
|
return -EIO;
|
2016-09-28 00:29:55 +08:00
|
|
|
}
|
|
|
|
|
2017-02-28 19:51:55 +08:00
|
|
|
/* start to converting mailbox */
|
|
|
|
convert:
|
2017-08-31 05:24:54 +08:00
|
|
|
fprintf(stdout, "using %2.2fMHz timestamp clock\n", clk);
|
|
|
|
|
2016-09-28 00:29:55 +08:00
|
|
|
while (1) {
|
|
|
|
count = fread(&tmp[0], 1, 4, in_fd);
|
|
|
|
if (count != 4)
|
|
|
|
break;
|
|
|
|
|
|
|
|
val = *((uint32_t*)tmp);
|
|
|
|
|
|
|
|
c = tmp[0];
|
|
|
|
tmp[0] = tmp[3];
|
|
|
|
tmp[3] = c;
|
|
|
|
c = tmp[1];
|
|
|
|
tmp[1] = tmp[2];
|
|
|
|
tmp[2] = c;
|
|
|
|
|
|
|
|
if (addr >= MAILBOX_TRACE_OFFSET &&
|
|
|
|
addr < MAILBOX_TRACE_OFFSET + MAILBOX_TRACE_SIZE)
|
2017-06-09 21:55:36 +08:00
|
|
|
show_trace(val, addr, ×tamp, clk);
|
2016-09-28 00:29:55 +08:00
|
|
|
else if (addr >= MAILBOX_DEBUG_OFFSET &&
|
|
|
|
addr < MAILBOX_DEBUG_OFFSET + MAILBOX_DEBUG_SIZE)
|
|
|
|
show_debug(val, addr);
|
|
|
|
else if (addr >= MAILBOX_EXCEPTION_OFFSET &&
|
|
|
|
addr < MAILBOX_EXCEPTION_OFFSET + MAILBOX_EXCEPTION_SIZE)
|
|
|
|
show_exception(val, addr);
|
|
|
|
|
2017-02-28 19:51:55 +08:00
|
|
|
if (out_fd) {
|
|
|
|
count = fwrite(&tmp[0], 1, 4, out_fd);
|
|
|
|
if (count != 4)
|
|
|
|
break;
|
|
|
|
}
|
2016-09-28 00:29:55 +08:00
|
|
|
|
|
|
|
addr += 4;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* close files */
|
|
|
|
fclose(in_fd);
|
2017-02-28 19:51:55 +08:00
|
|
|
if (out_fd)
|
|
|
|
fclose(out_fd);
|
2016-09-28 00:29:55 +08:00
|
|
|
|
2017-02-28 19:51:55 +08:00
|
|
|
return 0;
|
2016-09-28 00:29:55 +08:00
|
|
|
}
|