blob: c77317ddec9e8db7400ce4e6918d0ebc0dfd20b6 [file] [log] [blame]
/*
* Copyright 2017, Data61
* Commonwealth Scientific and Industrial Research Organisation (CSIRO)
* ABN 41 687 119 230.
*
* This software may be distributed and modified according to the terms of
* the BSD 2-Clause license. Note that NO WARRANTY is provided.
* See "LICENSE_BSD2.txt" for details.
*
* @TAG(DATA61_BSD)
*/
#include "ehci.h"
/****** DEBUG printing *******/
static const char *dump_colour(enum usb_xact_status stat)
{
switch (stat) {
case XACTSTAT_PENDING:
return A_FG_Y;
case XACTSTAT_ERROR:
case XACTSTAT_HOSTERROR:
return A_FG_R;
case XACTSTAT_SUCCESS:
return A_FG_G;
default:
return "";
}
}
void dump_qtd(volatile struct TD *qtd)
{
int pid;
uint32_t tok;
const char *col = dump_colour(qtd_get_status(qtd));
printf("%s", col);
printf("-- td 0x%08x\n", (uint32_t) qtd);
printf("%s", col);
printf("- next: 0x%08x | 0x%08x (%s)\n",
qtd->next, qtd->next & ~0x1f,
(qtd->next & 0x1) ? "TERMINATE" : "CONTINUE");
printf("- altnext: 0x%08x | 0x%08x (%s)\n",
qtd->alt, qtd->alt & ~0x1f,
(qtd->alt & 0x1) ? "TERMINATE" : "CONTINUE");
/* Complicated token */
tok = qtd->token;
printf("- token: 0x%08x | ", tok);
printf("%s", (tok & (1UL << 31)) ? "TOG;" : "");
printf("totx %d;", (tok >> 16) & 0x7fff);
printf("%s", (tok & (1UL << 15)) ? "IOC;" : "");
printf("page %d;", (tok >> 12) & 0x7);
printf("errs %d;", (tok >> 10) & 0x3);
pid = (tok >> 8) & 0x3;
printf("pid %d (%s)", pid, (pid == 0) ? "OUT" :
(pid == 1) ? "IN" : (pid == 2) ? "SETUP" : "RES");
if (tok & BIT(7)) {
printf(";ACTIVE");
}
if (tok & BIT(6)) {
printf(";HALTED");
}
if (tok & BIT(5)) {
printf(";BUFFER ERROR");
}
if (tok & BIT(4)) {
printf(";BABBLE DETECTED");
}
if (tok & BIT(3)) {
printf(";TRANSACTION ERR");
}
if (tok & BIT(2)) {
printf(";MISSED uFRAME");
}
if (tok & BIT(1)) {
printf(";COMPLETE SPLIT");
}
if (tok & BIT(0)) {
printf(";DO PING");
}
printf("\n");
/* buffer list */
{
int i;
for (i = 0; i < 5; i++) {
if (qtd->buf[i] & ~(0x1000 - 1)) {
printf("- buffer%d: 0x%08x | 0x%08x",
i, qtd->buf[i], qtd->buf[i] & ~0xfff);
if (i == 0) {
printf(" (0x%x bytes left)\n",
qtd->buf[i] & 0xfff);
} else {
printf("\n");
}
}
}
}
printf(A_FG_RESET);
}
void dump_qhn(struct QHn *qhn)
{
uint32_t v;
volatile struct QH *qh;
const char *col;
col = dump_colour(qhn_get_status(qhn));
qh = qhn->qh;
printf("%s", col);
printf("++ qh 0x%08x(0x%08x)\n", (uint32_t) qh, (uint32_t) qhn->pqh);
printf("%s", col);
printf("+ link: 0x%08x | 0x%08x (%s|",
qh->qhlptr, qh->qhlptr & ~0xf,
(qh->qhlptr & 0x1) ? "TERMINATE" : "CONTINUE");
switch ((qh->qhlptr >> 1) & 0x3) {
case 0:
printf("ITD)\n");
break;
case 1:
printf("QH)\n");
break;
case 2:
printf("SITD)\n");
break;
case 3:
printf("FSTN)\n");
break;
}
v = qh->epc[0];
printf("+ epc0: 0x%08x| addr %d(%d); NAC reload %d;max pkt %d",
v, v & 0x7f, (v >> 8) & 0xf, v >> 28, (v >> 16) & 0x7ff);
if (v & (1 << 27)) {
printf(";C");
}
if (v & (1 << 15)) {
printf(";H");
}
if (v & (1 << 14)) {
printf(";DTC");
}
if (v & (1 << 7)) {
printf(";I");
}
v = (v >> 12) & 0x3;
switch (v) {
case 0:
printf("; 12Mbs");
break;
case 1:
printf(";1.5Mbs");
break;
case 2:
printf(";480Mbs");
break;
case 3:
printf(";???Mbs");
break;
}
printf("\n");
printf("C-PROG Mask: 0x%x s-bytes 0x%x frametag 0x%x\n",
(qh->td_overlay.buf[1] >> 0) & 0xff,
(qh->td_overlay.buf[2] >> 5) & 0x7f,
(qh->td_overlay.buf[2] >> 0) & 0x1f);
v = qh->epc[1];
printf("+ epc1: 0x%08x; hub %d; port %d; txc %d; uF c%d s%d\n",
v, (v >> 16) & 0x7f, (v >> 23) & 0x7f, v >> 30,
(v >> 8) & 0xff, v & 0xff);
printf("+ current: 0x%08x\n", qh->td_cur);
dump_qtd(&qh->td_overlay);
struct TDn *tdn = qhn->tdns;
while (tdn) {
printf("-- ptd 0x%08x\n", tdn->ptd);
dump_qtd(tdn->td);
tdn = tdn->next;
}
printf(A_FG_RESET);
}
void UNUSED dump_q(struct QHn *qhn)
{
int i = 1;
struct QHn *head = qhn;
printf("##### Start Async list #####\n");
do {
printf("{QH %d}\n", i++);
dump_qhn(qhn);
qhn = qhn->next;
} while (qhn && qhn != head);
printf("##### End Async list #####\n");
}
void UNUSED dump_edev(struct ehci_host *edev)
{
uint32_t sts, cmd, intr;
sts = edev->op_regs->usbsts;
cmd = edev->op_regs->usbcmd;
intr = edev->op_regs->usbintr;
printf("*** EHCI edevice ***\n");
printf("* usbcmd\n");
printf(" IRQ threshold: 0x%x\n", (cmd >> 16) & 0xff);
printf(" async parked: %s\n",
(cmd & EHCICMD_ASYNC_PARK) ? "yes" : "no");
printf(" async park mode: %d\n", (cmd >> 8) & 0x3);
printf(" light reset: %s\n",
(cmd & EHCICMD_LIGHT_RST) ? "yes" : "no");
printf(" async doorbell: %s\n",
(cmd & EHCICMD_ASYNC_DB) ? "yes" : "no");
printf(" async: %s\n",
(cmd & EHCICMD_ASYNC_EN) ? "Enabled" : "Disabled");
printf(" frame list size: ");
switch (cmd & EHCICMD_LIST_SMASK) {
case EHCICMD_LIST_S1024:
printf("1024\n");
break;
case EHCICMD_LIST_S512:
printf("512\n");
break;
case EHCICMD_LIST_S256:
printf("256\n");
break;
default:
printf("Unknown\n");
}
printf(" hcreset: %s\n",
(cmd & EHCICMD_HCRESET) ? "yes" : "no");
printf(" hcrunstop: %s\n",
(cmd & EHCICMD_RUNSTOP) ? "yes" : "no");
printf("* usbsts\n");
printf(" async en: %s\n",
(sts & EHCISTS_ASYNC_EN) ? "yes" : "no");
printf(" periodic en: %s\n",
(sts & EHCISTS_PERI_EN) ? "yes" : "no");
printf(" async empty: %s\n",
(sts & EHCISTS_ASYNC_EMPTY) ? "yes" : "no");
printf(" hc halted: %s\n",
(sts & EHCISTS_HCHALTED) ? "yes" : "no");
printf(" async advance: %s\n",
(sts & EHCISTS_ASYNC_ADV) ? "yes" : "no");
printf(" host err: %s\n",
(sts & EHCISTS_HOST_ERR) ? "yes" : "no");
printf(" frame list roll: %s\n",
(sts & EHCISTS_FLIST_ROLL) ? "yes" : "no");
printf(" port change: %s\n",
(sts & EHCISTS_PORTC_DET) ? "yes" : "no");
printf(" usb err: %s\n",
(sts & EHCISTS_USBERRINT) ? "yes" : "no");
printf(" usb event: %s\n", (sts & EHCISTS_USBINT) ? "yes" : "no");
printf("* usbintr\n");
printf(" async advance: %s\n",
(intr & EHCIINTR_ASYNC_ADV) ? "yes" : "no");
printf(" host err: %s\n",
(intr & EHCIINTR_HOST_ERR) ? "yes" : "no");
printf(" frame list roll: %s\n",
(intr & EHCIINTR_FLIST_ROLL) ? "yes" : "no");
printf(" port change: %s\n",
(intr & EHCIINTR_PORTC_DET) ? "yes" : "no");
printf(" usb err: %s\n",
(intr & EHCIINTR_USBERRINT) ? "yes" : "no");
printf(" usb event: %s\n",
(intr & EHCIINTR_USBINT) ? "yes" : "no");
printf(" * Frame index: 0x%x\n", edev->op_regs->frindex);
printf(" * periodic base: 0x%x\n", edev->op_regs->periodiclistbase);
printf(" * async base: 0x%x\n", edev->op_regs->asynclistaddr);
}