OpenCores
URL https://opencores.org/ocsvn/mips_enhanced/mips_enhanced/trunk

Subversion Repositories mips_enhanced

[/] [mips_enhanced/] [trunk/] [grlib-gpl-1.0.19-b3188/] [software/] [leon3/] [grusbhc.c] - Rev 2

Compare with Previous | Blame | View Log

/*
 * Tests for GRUSBHC
 *
 * Copyright (c) 2008 Gaisler Research AB
 *
 * Test functions:
 * ehc_test(..):     Tests EHC only
 * uhc_test(..):     Tests UHC only 
 * grusbhc_test(..): Tests UHC by calling uhc_test(..), then tests EHC by calling
 *                   ehc_test(..). If a address argument for a controller is 0 the
 *                   test for that controller will be skipped.
 * 
 * This test application transfers data but skips device resets and enumeration. 
 * It will not work with a real USB device.
 *
 * Requirements on simulation environment:
 * All ports must be connected to the utmi or ulpi simulation model
 * available in the gaisler simulation library lib/gaisler/sim.
 */
 
#include "testmod.h"
#include <malloc.h>
 
/***********/
/* Helpers */          
/***********/
 
#define byte_swap(x) ((((x) >> 24) & 0xff) | (((x) >> 8) & 0xff00) | \
		      (((x) << 8) & 0xff0000) | ((x) << 24))
 
#define cond_bswap(x, be) (be ? (x) : byte_swap(x))
 
#define hword_swap(x) ((((x) >> 16) & 0xffff) | ((x) << 16))
 
 
int *build_frame_list(int nelem, int bedesc)
{
  int i;
  int *flbase;
 
  flbase = memalign(4096, nelem*4);
 
  for (i = 0; i < nelem; i++)
    if (bedesc = 1)
      *(flbase + i) = 1;
    else 
      *(flbase + i) = 0x01000000;
 
  return flbase;
}
 
/*********************/
/* EHC specific code */
/*********************/
 
/* Register fields */
/* USBCMD */
#define EHC_USBCMD_ITHRES          (0xff << 16)
#define EHC_USBCMD_ITHRES_P        16
#define EHC_USBCMD_PMODE           (1 << 11)
#define EHC_USBCMD_PMODECNT        (3 << 8)
#define EHC_USBCMD_LHCRESET        (1 << 7)
#define EHC_USBCMD_AS_ADV_INT      (1 << 6)
#define EHC_USBCMD_AS_SCHED_EN     (1 << 5)
#define EHC_USBCMD_PER_SCHED_EN    (1 << 4)
#define EHC_USBCMD_FLSIZE          (3 << 2)
#define EHC_USBCMD_HCRESET         (1 << 1)
#define EHC_USBCMD_RUNSTOP         (1 << 0)
 
/* USBSTS */
#define EHC_USBSTS_ASSTAT          (1 << 15)
#define EHC_USBSTS_PERSTAT         (1 << 14)
#define EHC_USBSTS_RECL            (1 << 13)
#define EHC_USBSTS_HCHALTED        (1 << 12)
#define EHC_USBSTS_ASADV           (1 << 5)
#define EHC_USBSTS_HSERR           (1 << 4)
#define EHC_USBSTS_FLROLL          (1 << 3)
#define EHC_USBSTS_PCHANGE_DETECT  (1 << 2)
#define EHC_USBSTS_USBERRINT       (1 << 1)
#define EHC_USBSTS_USBINT          (1 << 0)
 
/* CONFIGFLAG */
#define EHC_CONFIGFLAG_CF          (1 << 0)
 
/* PORTSC */
#define EHC_PORTSC_WKOC_E          (1 << 22)
#define EHC_PORTSC_WKDSCNNT_E      (1 << 21)
#define EHC_PORTSC_WKCNNT_E        (1 << 20)
#define EHC_PORTSC_POWNER          (1 << 13)
#define EHC_PORTSC_PP              (1 << 12)
#define EHC_PORTSC_LS_P            10
#define EHC_PORTSC_PRESET          (1 << 8)
#define EHC_PORTSC_PSUSPEND        (1 << 7)
#define EHC_PORTSC_PRESUME         (1 << 6)
#define EHC_PORTSC_OC_CHANGE       (1 << 5)
#define EHC_PORTSC_OC_ACTIVE       (1 << 4)
#define EHC_PORTSC_PEN_CHANGE      (1 << 3)
#define EHC_PORTSC_PEN             (1 << 2)
#define EHC_PORTSC_CNNTSTAT_CHANGE (1 << 1)
#define EHC_PORTSC_CNNTSTAT        (1 << 0)
 
#define EHC_JSTATE 0x2
 
#define EHC_AUXREGS_OFF 0x54
 
#define EHC_USBCMD_RESVAL(aspm)  (aspm ? 0x00080b00 : 0x00080000)
#define EHC_USBSTS_RESVAL        0x00001000
#define EHC_USBINTR_RESVAL       0x00000000
#define EHC_FRINDEX_RESVAL       0x00000000
#define EHC_CTRLDSSEGMENT_RESVAL 0x00000000
#define EHC_CONFIGFLAG_RESVAL    0x00000000
#define EHC_PORTSC_RESVAL(ppc)   (ppc ? 0x00002000  : 0x00003000)        
 
#define EHC_HCSPARAMS_NPORTS(x) (x & 0xf)
#define EHC_HCSPARAMS_PPC(x)    (x & 0x10)
 
#define EHC_HCCPARAMS_ASPM(x)   (x & 0x4)
 
struct ehccoreregs {
  volatile unsigned int capver;
  volatile unsigned int hcsparams;
  volatile unsigned int hccparams;
  volatile unsigned int hcspportroute[2];
  volatile unsigned int usbcmd;
  volatile unsigned int usbsts;
  volatile unsigned int usbintr;
  volatile unsigned int frindex;
  volatile unsigned int ctrldssegment;
  volatile unsigned int perlistbase;
  volatile unsigned int alistaddr;
};
 
struct ehcauxregs {
  volatile unsigned int configflag;
  volatile unsigned int portsc[15];
};
 
/* Descriptor fields and helper defines */
 
#define EHC_TYP_iTD     0x00
#define EHC_TYP_QH      0x02
#define EHC_T           (1 << 0)
 
#define EHC_HS          2
 
#define iTD_STATUS_P    28
#define iTD_ACTIVE      (1 << 3)
#define iTD_TLEN_P      16
#define iTD_IOC         (1 << 15)
#define iTD_IO          (1 << 11)
 
#define QH_RL_P         28
#define QH_C            (1 << 27)
#define QH_MAXP_P       16
#define QH_H            (1 << 15)
#define QH_DTC          (1 << 14)
#define QH_EPS_P        12
#define QH_ENDPT_P      8
#define QH_MULT_P       30
 
#define qTD_DT          (1 << 31)
#define qTD_TOTALB_P    16
#define qTD_IOC         (1 << 15) 
#define qTD_PID_P       8
#define qTD_ACTIVE      0x80
#define qTD_HALTBABXACT 0x58
 
#define qTD_OUT         0
#define qTD_IN          1
#define qTD_SETUP       10
 
#define MASK_UFRAME0    0x01
#define MASK_UFRAME1    0x02
 
 
struct ehc_itd {
  volatile unsigned int lp;
  volatile unsigned int status[8];
  volatile unsigned int buf[7];
};
 
struct ehc_qtd {
  volatile unsigned int next;
  volatile unsigned int anext;
  volatile unsigned int token;
  volatile unsigned int bufp[4];
 
};
 
struct ehc_qh {
  volatile unsigned int lp;
  volatile unsigned int chr;
  volatile unsigned int cap;
  volatile unsigned int curr;
  struct ehc_qtd qtd;
};
 
 
void ehc_check_opresvals(struct ehccoreregs *c, struct ehcauxregs *a, 
			 int beregs)
{
  int i = 0;
  int nports = EHC_HCSPARAMS_NPORTS(cond_bswap(c->hcsparams,beregs));
  int aspm =  EHC_HCCPARAMS_ASPM(cond_bswap(c->hccparams,beregs));
  int ppc = EHC_HCSPARAMS_PPC(cond_bswap(c->hcsparams,beregs));
 
  if (c->usbcmd != cond_bswap(EHC_USBCMD_RESVAL(aspm),beregs))
    fail(0);
  if (c->usbsts != cond_bswap(EHC_USBSTS_RESVAL,beregs))
    fail(1);
  if (c->usbintr != cond_bswap(EHC_USBINTR_RESVAL,beregs))
    fail(2);
  if (c->frindex != cond_bswap(EHC_FRINDEX_RESVAL,beregs))
    fail(3);
  if (c->ctrldssegment != cond_bswap(EHC_CTRLDSSEGMENT_RESVAL,beregs))
    fail(4);
  /* Periodic List Base has undefined reset value, not checked */
  /* Asynchronous List Address has undefined reset value, not checked */
  if (a->configflag != cond_bswap(EHC_CONFIGFLAG_RESVAL,beregs))
    fail(5);
  while (i < nports) {
    if (a->portsc[i] != cond_bswap(EHC_PORTSC_RESVAL(ppc),beregs))
      fail(6+i);
    i++;
  }
}
 
 
int ehc_test(int addr, int bedesc, int beregs)
{
  int i;
 
  char *buf;
  int *flbase;
 
  struct ehccoreregs *c;
  struct ehcauxregs *a;
 
  struct ehc_itd *itdi, *itdo;
  struct ehc_qh *qhi, *qho, *aqh;
  struct ehc_qtd *qtdi, *qtdo, *aqtdi, *aqtdo;
 
 
  report_device(0x01026000);
 
  c = (struct ehccoreregs*)addr;
  a = (struct ehcauxregs*)(addr + EHC_AUXREGS_OFF);
 
  /* Check register reset values */
  report_subtest(1);
 
  ehc_check_opresvals(c, a, beregs);
 
  /* Perform HC Reset */
  report_subtest(2);
 
  c->usbcmd |= cond_bswap(EHC_USBCMD_HCRESET, beregs);
 
  while (c->usbcmd & cond_bswap(EHC_USBCMD_HCRESET,beregs))
    ;
 
  ehc_check_opresvals(c, a, beregs);
 
  /* Activate controller, reset device and transfer 1 byte isoch OUT and IN, 
     1 byte interrupt OUT and IN */
  report_subtest(3);
 
  a->configflag = cond_bswap(EHC_CONFIGFLAG_CF,beregs);
 
  if (EHC_HCSPARAMS_PPC(cond_bswap(c->hcsparams,beregs)))
    a->portsc[0] = cond_bswap(EHC_PORTSC_PP, beregs);
 
  while (!(a->portsc[0] & cond_bswap(EHC_PORTSC_CNNTSTAT, beregs)))
    ;
 
  /* Controller should discover connect */
  if (a->portsc[0] != cond_bswap(EHC_PORTSC_PP | 
				 (EHC_JSTATE << EHC_PORTSC_LS_P) |
				 EHC_PORTSC_CNNTSTAT_CHANGE |
				 EHC_PORTSC_CNNTSTAT, beregs))
    fail(0);
 
  a->portsc[0] |= cond_bswap(EHC_PORTSC_PRESET,beregs);
 
  /* Build schedule */
  flbase = build_frame_list(2, bedesc);
 
  if ((itdi = memalign(32, sizeof(struct ehc_itd))) == NULL)
    fail(1);
  if ((itdo = memalign(32, sizeof(struct ehc_itd))) == NULL)
    fail(2);
  if ((qhi = memalign(32, sizeof(struct ehc_qh))) == NULL)
    fail(3);
  if ((qho = memalign(32, sizeof(struct ehc_qh))) == NULL)
    fail(4);
  if ((qtdi = memalign(32, sizeof(struct ehc_qtd))) == NULL)
    fail(5);
  if ((qtdo = memalign(32, sizeof(struct ehc_qtd))) == NULL)
    fail(6);
 
  if ((buf = memalign(4096, 2)) == NULL)
    fail(7);
 
  *buf = 0xaa;
  *(buf+1) = 0xbb;
 
  itdo->lp = cond_bswap((int)itdi,bedesc);
  itdo->status[0] = cond_bswap((iTD_ACTIVE << iTD_STATUS_P) | 
			       (1 << iTD_TLEN_P),bedesc);
  for (i = 1; i < 8; i++)
    itdo->status[i] = 0;
  itdo->buf[0] = cond_bswap((int)buf,bedesc);
  itdo->buf[1] = cond_bswap(1,bedesc);
  itdo->buf[2] = cond_bswap(1,bedesc);
  itdi->lp = cond_bswap((int)qho | EHC_TYP_QH ,bedesc);
  itdi->status[0] = cond_bswap((iTD_ACTIVE << iTD_STATUS_P) | 
			       (1 << iTD_TLEN_P),bedesc);
  for (i = 1; i < 8; i++)
    itdi->status[i] = 0;
  itdi->buf[0] = cond_bswap((int)buf,bedesc);
  itdi->buf[1] = cond_bswap(iTD_IO | 1,bedesc);
  itdi->buf[2] = cond_bswap(1,bedesc);
 
  qho->lp = cond_bswap((int)qhi | EHC_TYP_QH,bedesc);
  qho->chr = cond_bswap((1 << QH_MAXP_P) | (EHC_HS << QH_EPS_P) | 
			(1 << QH_ENDPT_P),bedesc);
  qho->cap = cond_bswap(1 << QH_MULT_P | MASK_UFRAME0,bedesc);
  qho->curr = cond_bswap((int)qtdo,bedesc);
  qho->qtd.next = cond_bswap(EHC_T,bedesc);
  qho->qtd.anext = cond_bswap(EHC_T,bedesc);
  qho->qtd.token = cond_bswap((1 << qTD_TOTALB_P) | 
			      (qTD_OUT << qTD_PID_P) | qTD_ACTIVE,bedesc);
  qho->qtd.bufp[0] = cond_bswap((int)buf | 1,bedesc);
  qtdo->next = cond_bswap(EHC_T,bedesc);
  qtdo->anext = cond_bswap(EHC_T,bedesc);
  qtdo->token = cond_bswap((1 << qTD_TOTALB_P) | 
			      (qTD_OUT << qTD_PID_P) | qTD_ACTIVE,bedesc);
  qtdo->bufp[0] = cond_bswap((int)buf | 1,bedesc);
 
  qhi->lp = cond_bswap(EHC_T,bedesc);
  qhi->chr = cond_bswap((1 << QH_MAXP_P) | (EHC_HS << QH_EPS_P) |
			(1 << QH_ENDPT_P),bedesc);
  qhi->cap = cond_bswap(1 << QH_MULT_P | MASK_UFRAME0,bedesc);
  qhi->curr = cond_bswap((int)qtdi,bedesc);
  qhi->qtd.next = cond_bswap(EHC_T,bedesc);
  qhi->qtd.anext = cond_bswap(EHC_T,bedesc);
  qhi->qtd.token = cond_bswap((1 << qTD_TOTALB_P) | qTD_IOC | 
			      (qTD_IN << qTD_PID_P) | qTD_ACTIVE,bedesc);
  qhi->qtd.bufp[0] = cond_bswap((int)buf | 1,bedesc);
  qtdi->next = cond_bswap(EHC_T,bedesc);
  qtdi->anext = cond_bswap(EHC_T,bedesc);
  qtdi->token = cond_bswap((1 << qTD_TOTALB_P) | qTD_IOC | 
			      (qTD_IN << qTD_PID_P) | qTD_ACTIVE,bedesc);
  qtdi->bufp[0] = cond_bswap((int)buf | 1,bedesc);
 
  flbase[0] = cond_bswap((int)itdo,bedesc);
 
  c->perlistbase = cond_bswap((int)flbase,beregs);
 
  /* If the processor is operating at a high frequency we may
     set port reset to 0 too fast */
  a->portsc[0] &= cond_bswap(~EHC_PORTSC_PRESET,beregs);
 
  while (!(a->portsc[0] & cond_bswap(EHC_PORTSC_PEN,beregs)))
    ;
 
  c->usbsts = c->usbsts;
 
  c->usbcmd = cond_bswap((1 << EHC_USBCMD_ITHRES_P) | EHC_USBCMD_PER_SCHED_EN | 
			 EHC_USBCMD_RUNSTOP,beregs);
 
  /* Build schedule for test 4 */
  aqh = memalign(32, sizeof(struct ehc_qh));
  aqtdi = memalign(32, sizeof(struct ehc_qtd));
  aqtdo = memalign(32, sizeof(struct ehc_qtd));
 
  aqh->lp = cond_bswap((int)aqh,bedesc);
  aqh->chr = cond_bswap((1 << QH_MAXP_P) | QH_H | QH_DTC | 
			(EHC_HS << QH_EPS_P) | (1 << QH_ENDPT_P),bedesc);
  aqh->cap = cond_bswap(1 << QH_MULT_P,bedesc);
  aqh->curr = cond_bswap((int)aqtdo,bedesc);
  aqh->qtd.next = cond_bswap((int)aqtdi,bedesc);
  aqh->qtd.anext = cond_bswap(EHC_T,bedesc);
  aqh->qtd.token = cond_bswap((1 << qTD_TOTALB_P) | qTD_IOC | 
			      (qTD_OUT << qTD_PID_P) | qTD_ACTIVE,bedesc);
  aqh->qtd.bufp[0] = cond_bswap((int)buf,bedesc);
  aqtdo->next = cond_bswap((int)aqtdi,bedesc);
  aqtdo->anext = cond_bswap(EHC_T,bedesc);
  aqtdo->token = cond_bswap((1 << qTD_TOTALB_P) | qTD_IOC |
			    (qTD_OUT << qTD_PID_P) | qTD_ACTIVE,bedesc);
  aqtdo->bufp[0] = cond_bswap((int)buf,bedesc);
 
  aqtdi->next = cond_bswap(EHC_T,bedesc);
  aqtdi->anext = cond_bswap(EHC_T,bedesc);
  aqtdi->token = cond_bswap((qTD_IN << qTD_PID_P) | qTD_ACTIVE,bedesc);
  aqtdi->bufp[0] = cond_bswap((int)buf,bedesc);
 
 
  while (!(c->usbsts & cond_bswap(EHC_USBSTS_USBINT,beregs)))
    ;
 
  if (c->usbsts != cond_bswap(EHC_USBSTS_PERSTAT |
			      EHC_USBSTS_USBINT, beregs))
    fail(2);
 
  if (itdo->lp != cond_bswap((int)itdi,bedesc))
    fail(3);
  if (itdo->status[0] != cond_bswap((1 << iTD_TLEN_P) | 1,bedesc))
    fail(4);
  if (itdo->buf[0] != cond_bswap((int)buf,bedesc))
    fail(5);
  if (itdo->buf[1] != cond_bswap(1,bedesc))
    fail(6);
  if (itdo->buf[2] != cond_bswap(1,bedesc))
    fail(7);
  if (itdi->lp != cond_bswap((int)qho | EHC_TYP_QH ,bedesc))
    fail(8);
  if (itdi->status[0] != cond_bswap((1 << iTD_TLEN_P) | 1,bedesc))
    fail(9);
  if (itdi->buf[0] != cond_bswap((int)buf,bedesc))
    fail(10);
  if (itdi->buf[1] != cond_bswap(iTD_IO | 1,bedesc))
    fail(11);
  if (itdi->buf[2] != cond_bswap(1,bedesc))
    fail(12);
 
  if (*buf != 0x55)
    fail(13);
 
  if (qho->lp != cond_bswap((int)qhi | EHC_TYP_QH,bedesc))
    fail(14);
  if (qho->chr != cond_bswap((1 << QH_MAXP_P) | (EHC_HS << QH_EPS_P) |
			     (1 << QH_ENDPT_P),bedesc))
    fail(15);
  if (qho->cap != cond_bswap(1 << QH_MULT_P | MASK_UFRAME0,bedesc))
    fail(16);
  if (qho->curr != cond_bswap((int)qtdo,bedesc))
    fail(17);
  if (qho->qtd.next != cond_bswap(EHC_T,bedesc))
    fail(18);
  if (qho->qtd.anext != cond_bswap(EHC_T,bedesc))
    fail(19);
  if (qho->qtd.token != cond_bswap(qTD_DT | (qTD_OUT << qTD_PID_P),bedesc))
    fail(20);
  if (qho->qtd.bufp[0] != cond_bswap((int)buf | 2,bedesc))
    fail(21);
  if (qtdo->next != cond_bswap(EHC_T,bedesc))
    fail(22);
  if (qtdo->anext != cond_bswap(EHC_T,bedesc))
    fail(23);
  if (qtdo->token != cond_bswap(qTD_DT | (qTD_OUT << qTD_PID_P),bedesc))
    fail(24);
  if (qtdo->bufp[0] != cond_bswap((int)buf | 1,bedesc))
    fail(25);
 
  if (qhi->lp != cond_bswap(EHC_T,bedesc))
    fail(26);
  if (qhi->chr != cond_bswap((1 << QH_MAXP_P) | (EHC_HS << QH_EPS_P) |
			     (1 << QH_ENDPT_P),bedesc))
    fail(27);
  if (qhi->cap != cond_bswap(1 << QH_MULT_P | MASK_UFRAME0,bedesc))
    fail(28);
  if (qhi->curr != cond_bswap((int)qtdi,bedesc))
    fail(29);
  if (qhi->qtd.next != cond_bswap(EHC_T,bedesc))
    fail(30);
  if (qhi->qtd.anext != cond_bswap(EHC_T,bedesc))
    fail(31);
  if (qhi->qtd.token != cond_bswap(qTD_DT | qTD_IOC | 
				   (qTD_IN << qTD_PID_P),bedesc))
    fail(32);
  if (qhi->qtd.bufp[0] != cond_bswap((int)buf | 2,bedesc))
    fail(33);
  if (qtdi->next != cond_bswap(EHC_T,bedesc))
    fail(34);
  if (qtdi->anext != cond_bswap(EHC_T,bedesc))
    fail(35);
  if (qtdi->token != cond_bswap(qTD_DT | qTD_IOC | 
				(qTD_IN << qTD_PID_P),bedesc))
    fail(36);
  if (qtdi->bufp[0] != cond_bswap((int)buf | 1,bedesc))
    fail(37);
 
  if (*(buf+1) != 0x44)
    fail(38);
 
  c->usbsts = c->usbsts;
 
  /* Transfer 1b SETUP OUT and 0b bulk IN which should lead to babble error, 
     first traverse inactive per. sched. */
  report_subtest(4);
 
  c->alistaddr = cond_bswap((int)aqh,beregs);
 
  /* Enable both schedules */
  c->usbcmd = cond_bswap((1 << EHC_USBCMD_ITHRES_P) | EHC_USBCMD_PER_SCHED_EN | 
			 EHC_USBCMD_AS_SCHED_EN | EHC_USBCMD_RUNSTOP,beregs);
 
  while (!(c->usbsts & cond_bswap(EHC_USBSTS_USBERRINT,beregs)))
    ;
 
  if (c->usbsts != cond_bswap(EHC_USBSTS_PERSTAT | EHC_USBSTS_ASSTAT |
			      EHC_USBSTS_USBERRINT | EHC_USBSTS_USBINT, beregs))
    fail(1);
 
  c->usbcmd = 0;
 
  if (aqh->lp != cond_bswap((int)aqh,bedesc))
    fail(2);
  if (aqh->chr != cond_bswap((1 << QH_MAXP_P) | QH_H | QH_DTC | 
			     (EHC_HS << QH_EPS_P) | (1 << QH_ENDPT_P),bedesc))
    fail(3);
  if (aqh->cap != cond_bswap(1 << QH_MULT_P,bedesc))
    fail(4);
  if (aqh->curr != cond_bswap((int)aqtdi,bedesc))
    fail(5);
  if (aqh->qtd.next != cond_bswap(EHC_T,bedesc))
    fail(6);
  if (aqh->qtd.anext != cond_bswap(EHC_T,bedesc))
    fail(7);
  if (aqh->qtd.token != cond_bswap((qTD_IN << qTD_PID_P) | qTD_HALTBABXACT,bedesc))
    fail(8);
  if (aqh->qtd.bufp[0] != cond_bswap((int)buf,bedesc))
    fail(9);
  if (aqtdo->next != cond_bswap((int)aqtdi,bedesc))
    fail(10);
  if (aqtdo->anext != cond_bswap(EHC_T,bedesc))
    fail(11);
  if (aqtdo->token != cond_bswap(qTD_DT | qTD_IOC | qTD_OUT << qTD_PID_P,bedesc))
    fail(12);
  if (aqtdo->bufp[0] != cond_bswap((int)buf,bedesc))
    fail(13);
  if (aqtdi->next != cond_bswap(EHC_T,bedesc))
    fail(14);
  if (aqtdi->anext != cond_bswap(EHC_T,bedesc))
    fail(15);
  if (aqtdi->token != cond_bswap((qTD_IN << qTD_PID_P) | qTD_HALTBABXACT,bedesc))
    fail(16);
  if (aqtdi->bufp[0] != cond_bswap((int)buf,bedesc))
    fail(17);
 
  free(itdi);
  free(itdo);
  free(qhi);
  free(qho);
  free(qtdi);
  free(qtdo);
  free(aqh);
  free(aqtdi);
  free(aqtdo);
  free(buf);
  free(flbase);
 
  while (!(c->usbsts & cond_bswap(EHC_USBSTS_HCHALTED,beregs)))
    ;
 
  a->configflag = 0;
 
  return 0;
}
 
/*********************/
/* UHC specific code */
/*********************/
 
/* Register fields */
/* USBCMD */
#define UHC_USBCMD_UMAXP      (1 << 7)
#define UHC_USBCMD_UCF        (1 << 6)
#define UHC_USBCMD_SWDBG      (1 << 5)
#define UHC_USBCMD_FGR        (1 << 4)
#define UHC_USBCMD_EGSM       (1 << 3)
#define UHC_USBCMD_GRESET     (1 << 2)
#define UHC_USBCMD_HCRESET    (1 << 1)
#define UHC_USBCMD_RUNSTOP    (1 << 0)
 
/* USBSTS */
#define UHC_USBSTS_HCHALTED   (1 << 5)
#define UHC_USBSTS_HCP        (1 << 4)
#define UHC_USBSTS_HCERROR    (1 << 3)
#define UHC_USBSTS_RSDETECT   (1 << 2)
#define UHC_USBSTS_USBERRINT  (1 << 1)
#define UHC_USBSTS_USBINT     (1 << 0)
 
/* PORTSC */
#define UHC_PORTSC_SUSPEND    (1 << 12)
#define UHC_PORTSC_PRESET     (1 << 9)
#define UHC_PORTSC_LS         (1 << 8)
#define UHC_PORTSC_RES        (1 << 7)
#define UHC_PORTSC_RSDETECT   (1 << 6)
#define UHC_PORTSC_LINESTATUS (3 << 4)
#define UHC_PORTSC_PEN_CHANGE (1 << 3)
#define UHC_PORTSC_PEN        (1 << 2)
#define UHC_PORTSC_CNNTSTATC  (1 << 1)
#define UHC_PORTSC_CNNTSTAT   (1 << 0)
 
/* Reset values */
#define UHC_USBCMD_RESVAL 0x0000
#define UHC_USBSTS_RESVAL 0x0020
#define UHC_USBINT_RESVAL 0x0000
#define UHC_FRNUM_RESVAL  0x0000
#define UHC_SOFMOD_RESVAL(b) (b ? 0x4000 : 0x40)
#define UHC_PORTSC_RESVAL 0x0083
 
struct uhcregs {
  volatile unsigned int usbcmdsts;
  volatile unsigned int usbintfrnum;
  volatile unsigned int fladdr;
  volatile unsigned int sofmod;
  volatile unsigned int portsc[4];
};
 
 
/* TD fields and helper defines */
#define TD_VF (1 << 2)
#define TD_Q  (1 << 1)
#define TD_T  (1 << 0)
 
#define TD_SPD (1 << 29)
#define TD_CERR_P 27
#define TD_LS (1 << 26)
#define TD_ISO (1 << 25)
#define TD_IOC (1 << 24)
#define TD_STATUS (255 << 16)
#define TD_STATUS_P 16
#define TD_STATUS_ACTIVE 0x80
#define TD_ACTIVE (TD_STATUS_ACTIVE << TD_STATUS_P)
#define TD_MAXLEN_P 21
#define TD_ENDPT_P 15
#define TD_D (1 << 19)
 
 
/* PIDS */
#define TD_PID_IN    0x69
#define TD_PID_OUT   0xE1
#define TD_PID_SETUP 0x2D
 
struct uhc_td {
  volatile unsigned int lp;
  volatile unsigned int stat;
  volatile unsigned int token;
  volatile unsigned int bufp;
};
 
struct uhc_qh {
  volatile unsigned int lp;
  volatile unsigned int elp;
  volatile unsigned int pad1;
  volatile unsigned int pad2;
};
 
 
#define get_lhw(x) ((x >> 16) & 0xffff)
#define get_hhw(x) (x & 0xffff)
 
#define fix_end(x) (beregs ? x : hword_swap(byte_swap(x)))  
 
#define cond_regswap(x) (beregs ? x : byte_swap(hword_swap(x)))
 
#define get_usbcmd(x) get_lhw(fix_end(x->usbcmdsts))
#define get_usbsts(x) get_hhw(fix_end(x->usbcmdsts))
#define get_usbint(x) get_lhw(fix_end(x->usbintfrnum))
#define get_frnum(x)  get_hhw(fix_end(x->usbintfrnum))
#define get_fladdr(x) byte_swap(x->fladdr)
#define get_sofmod(x) get_lhw(fix_end(x->sofmod))
#define get_portsc(x, i) (i % 2 ? get_hhw(fix_end(x->portsc[i/2])) : get_lhw(fix_end(x->portsc[i/2])))
 
void uhc_check_resvals(struct uhcregs *regs, int beregs)
{
  int i = 0;
 
  if (get_usbcmd(regs) != UHC_USBCMD_RESVAL)
    fail(0);
  if (get_usbsts(regs) != UHC_USBSTS_RESVAL)
    fail(1);
  if (get_usbint(regs) != UHC_USBINT_RESVAL)
    fail(2);
  if (get_frnum(regs) != UHC_FRNUM_RESVAL)
    fail(3);
  /* fladdr has undefined reset value */
  if (get_sofmod(regs) != UHC_SOFMOD_RESVAL(beregs))
    fail(4);
  while (get_portsc(regs,i) & UHC_PORTSC_RES) {
    if (get_portsc(regs,i) != UHC_PORTSC_RESVAL)
      fail(5+i);
    i++;
  }
}
 
 
int uhc_test(int addr, int bedesc, int beregs)
{
  int i;
 
  struct uhc_td *td;
  struct uhc_qh *qh;
  char *buf;
  int *flbase;
  struct uhcregs *regs;
 
  report_device(0x01027000);
 
  regs = (struct uhcregs*)addr;
 
  /* Check register reset values */
  report_subtest(1);
 
  uhc_check_resvals(regs, beregs);
 
  /* Perform HC reset */
  report_subtest(2);
 
  regs->usbcmdsts = cond_regswap(UHC_USBCMD_HCRESET);
 
  while (get_usbcmd(regs) & UHC_USBCMD_HCRESET)
    ;
 
  uhc_check_resvals(regs, beregs);
 
  /* Transfer 1 byte isoch packet OUT and IN */
  report_subtest(3);
 
  flbase = build_frame_list(2, bedesc);
 
  buf = malloc(1);
  td = memalign(16, 2*sizeof(struct uhc_td));
 
  *buf = 0xaa;
 
  td[0].lp = cond_bswap((int)(td+1), bedesc);
  td[0].stat = cond_bswap(TD_ISO | TD_ACTIVE, bedesc);
  td[0].token = cond_bswap(TD_PID_OUT, bedesc);
  td[0].bufp = cond_bswap((int)buf, bedesc);
 
  td[1].lp = cond_bswap(TD_T, bedesc);
  td[1].stat = cond_bswap(TD_ISO | TD_IOC | TD_ACTIVE, bedesc);
  td[1].token = cond_bswap(TD_PID_IN, bedesc);
  td[1].bufp = cond_bswap((int)buf, bedesc);
 
  flbase[0] = cond_bswap((int)td, bedesc);
 
  regs->fladdr = cond_bswap((int)flbase, beregs);
 
  regs->portsc[0] = cond_regswap(UHC_PORTSC_PEN << 16);
 
  regs->usbcmdsts = cond_regswap(UHC_USBCMD_RUNSTOP << 16);
 
  while (!get_usbsts(regs))
    ;
 
  if (!(get_usbsts(regs) & UHC_USBSTS_USBINT) || (get_usbsts(regs) >> 1))
    fail(0);
 
  regs->usbcmdsts = cond_regswap(0x0000ffff);
 
  if (!(get_usbsts(regs) & UHC_USBSTS_HCHALTED))
    fail(1);
 
 
  if (td[0].lp != cond_bswap((int)(td+1),bedesc))
    fail(2);
  if (td[0].stat != cond_bswap(TD_ISO,bedesc))
    fail(3);
  if (td[0].token != cond_bswap(TD_PID_OUT,bedesc))
    fail(4);
  if (td[0].bufp != cond_bswap((int)buf,bedesc))
    fail(5);
  if (td[1].lp != cond_bswap(TD_T,bedesc))
    fail(6);
  if (td[1].stat != cond_bswap(TD_ISO | TD_IOC,bedesc))
    fail(7);
  if (td[1].token != cond_bswap(TD_PID_IN,bedesc))
    fail(8);
  if (td[1].bufp != cond_bswap((int)buf,bedesc))
    fail(9);
  if (*buf != 0x55)
    fail(10);
 
  /* Transfer 0 byte control OUT and bulk IN */
  report_subtest(4);
 
  qh = memalign(16, 2*sizeof(struct uhc_qh));
 
  qh[0].lp = cond_bswap((int)(qh+1) | TD_Q,bedesc);
  qh[0].elp = cond_bswap((int)td,bedesc);
 
  qh[1].lp = cond_bswap(TD_T,bedesc);
  qh[1].elp = cond_bswap((int)(td+1),bedesc);
 
  td[0].lp = cond_bswap(TD_T,bedesc);
  td[0].stat = cond_bswap(TD_ACTIVE,bedesc);
  td[0].token = cond_bswap((0x7FF << TD_MAXLEN_P) | (1 << TD_ENDPT_P) | 
			   TD_PID_SETUP,bedesc);
  td[0].bufp = cond_bswap((int)buf,bedesc);
 
  td[1].lp = cond_bswap(TD_T,bedesc);
  td[1].stat = cond_bswap(TD_IOC | TD_ACTIVE,bedesc);
  td[1].token = cond_bswap((0x7FF << TD_MAXLEN_P) | (1 << TD_ENDPT_P) | 
			   TD_PID_IN,bedesc);
  td[1].bufp = cond_bswap((int)buf,bedesc);
 
  flbase[0] = cond_bswap((int)qh | TD_Q,bedesc);
 
  regs->usbcmdsts = cond_regswap(UHC_USBCMD_RUNSTOP << 16);
 
  while (!get_usbsts(regs))
    ;
 
  if (!(get_usbsts(regs) & UHC_USBSTS_USBINT) || (get_usbsts(regs) >> 1))
    fail(0);
 
  regs->usbcmdsts = cond_regswap(0x0000ffff);
 
  if (!(get_usbsts(regs) & UHC_USBSTS_HCHALTED))
    fail(1);
 
  if (td[0].lp != cond_bswap(TD_T,bedesc))
    fail(2);
  if (td[0].stat != cond_bswap(0x7ff,bedesc))
    fail(3);
  if (td[0].token != cond_bswap((0x7FF << TD_MAXLEN_P) | (1 << TD_ENDPT_P) | 
				TD_PID_SETUP,bedesc))
    fail(4);
  if (td[0].bufp != cond_bswap((int)buf,bedesc))
    fail(5);
  if (td[1].lp != cond_bswap(TD_T,bedesc))
    fail(6);
  if (td[1].stat != cond_bswap(TD_IOC | 0x7ff,bedesc))
    fail(7);
  if (td[1].token != cond_bswap((0x7FF << TD_MAXLEN_P) | (1 << TD_ENDPT_P) | 
				TD_PID_IN,bedesc))
    fail(8);
  if (td[1].bufp != cond_bswap((int)buf,bedesc))
    fail(9);
  if (*buf != 0x55)
    fail(10);
 
  if (qh[0].lp != cond_bswap((int)(qh+1) | TD_Q,bedesc))
    fail(11);
  if (qh[0].elp != cond_bswap(TD_T,bedesc))
    fail(12);
  if (qh[1].lp != cond_bswap(TD_T,bedesc))
    fail(13);
  if (qh[1].elp != cond_bswap(TD_T,bedesc))
    fail(14);
 
  free(td);
  free(qh);
  free(buf);
  free(flbase);
 
  return 0;
}
 
/*****************/
/* Complete test */
/*****************/
 
int grusbhc_test(int ehc_addr, int uhc_addr, int bedesc, int beregs)
{
  if (uhc_addr)
    uhc_test(uhc_addr, bedesc, beregs);
 
  if (ehc_addr)
    ehc_test(ehc_addr, bedesc, beregs);
 
  return 0;
}
 

Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.