/****************************************************************************
 * arch/arm/src/sama5/sam_usbhost.h
 *
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.  The
 * ASF licenses this file to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance with the
 * License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
 * License for the specific language governing permissions and limitations
 * under the License.
 *
 ****************************************************************************/

#ifndef __ARCH_ARM_SRC_SAMA5_SAM_USBHOST_H
#define __ARCH_ARM_SRC_SAMA5_SAM_USBHOST_H

/****************************************************************************
 * Included Files
 ****************************************************************************/

#include <nuttx/config.h>
#include <nuttx/usb/usbhost_trace.h>

#ifdef CONFIG_USBHOST

/****************************************************************************
 * Pre-processor Definitions
 ****************************************************************************/

/* This is the interface argument for call outs to board-specific functions
 * which need to know which USB host interface is being used.
 */

#define SAM_EHCI_IFACE 0
#define SAM_OHCI_IFACE 1

/* This is the interface argument for call outs to board-specific functions
 * which need to know which root hub port is being used.
 */

#define SAM_RHPORT1    0
#define SAM_RHPORT2    1
#define SAM_RHPORT3    2

/****************************************************************************
 * Public Types
 ****************************************************************************/

#ifdef HAVE_USBHOST_TRACE
enum usbhost_trace1codes_e
{
  __TRACE1_BASEVALUE = 0,       /* This will force the first value to be 1 */

#ifdef CONFIG_SAMA5_OHCI
  OHCI_TRACE1_DEVDISCONN,           /* OHCI ERROR: RHport Device disconnected */
  OHCI_TRACE1_INTRUNRECOVERABLE,    /* OHCI ERROR: Unrecoverable error */
  OHCI_TRACE1_INTRUNHANDLED,        /* OHCI ERROR: Unhandled interrupts */
  OHCI_TRACE1_EPLISTALLOC_FAILED,   /* OHCI ERROR: Failed to allocate EP list */
  OHCI_TRACE1_EDALLOC_FAILED,       /* OHCI ERROR: Failed to allocate ED */
  OHCI_TRACE1_TDALLOC_FAILED,       /* OHCI ERROR: Failed to allocate TD */
  OHCI_TRACE1_IRQATTACH,            /* OHCI ERROR: Failed to attach IRQ */
#ifdef CONFIG_USBHOST_ASYNCH
  OHCI_TRACE1_BADTDSTATUS,          /* OHCI ERROR: Bad asynch TD completion status */
#endif

#ifdef HAVE_USBHOST_TRACE_VERBOSE
  OHCI_VTRACE1_PHYSED,              /* OHCI physed */
  OHCI_VTRACE1_VIRTED,              /* OHCI ed */
  OHCI_VTRACE1_CSC,                 /* OHCI Connect Status Change */
  OHCI_VTRACE1_DRWE,                /* OHCI DRWE: Remote wake-up */
  OHCI_VTRACE1_ALREADYCONN,         /* OHCI Already connected */
  OHCI_VTRACE1_SPEED,               /* OHCI Low speed */
  OHCI_VTRACE1_ALREADYDISCONN,      /* OHCI Already disconnected */
  OHCI_VTRACE1_RHSC,                /* OHCI Root Hub Status Change */
  OHCI_VTRACE1_WDHINTR,             /* OHCI Writeback Done Head interrupt */
  OHCI_VTRACE1_CLASSENUM,           /* OHCI Enumerate the device */
  OHCI_VTRACE1_ENUMDISCONN,         /* OHCI RHport Not connected */
  OHCI_VTRACE1_INITIALIZING,        /* OHCI Initializing Stack */
  OHCI_VTRACE1_INITIALIZED,         /* OHCI Initialized */
  OHCI_VTRACE1_INTRPENDING,         /* OHCI Interrupts pending */
#endif
#endif

#ifdef CONFIG_SAMA5_EHCI
  EHCI_TRACE1_SYSTEMERROR,          /* EHCI ERROR: System error */
  EHCI_TRACE1_QTDFOREACH_FAILED,    /* EHCI ERROR: sam_qtd_foreach failed */
  EHCI_TRACE1_QHALLOC_FAILED,       /* EHCI ERROR: Failed to allocate a QH */
  EHCI_TRACE1_BUFTOOBIG,            /* EHCI ERROR: Buffer too big */
  EHCI_TRACE1_REQQTDALLOC_FAILED,   /* EHCI ERROR: Failed to allocate request qTD */
  EHCI_TRACE1_ADDBPL_FAILED,        /* EHCI ERROR: sam_qtd_addbpl failed */
  EHCI_TRACE1_DATAQTDALLOC_FAILED,  /* EHCI ERROR: Failed to allocate data buffer qTD */
  EHCI_TRACE1_DEVDISCONNECTED,      /* EHCI ERROR: Device disconnected */
  EHCI_TRACE1_QHCREATE_FAILED,      /* EHCI ERROR: sam_qh_create failed */
  EHCI_TRACE1_QTDSETUP_FAILED,      /* EHCI ERROR: sam_qtd_setupphase failed */
  EHCI_TRACE1_QTDDATA_FAILED,       /* EHCI ERROR: sam_qtd_dataphase failed */
  EHCI_TRACE1_QTDSTATUS_FAILED,     /* EHCI ERROR: sam_qtd_statusphase failed */
  EHCI_TRACE1_TRANSFER_FAILED,      /* EHCI ERROR: Transfer failed */
  EHCI_TRACE1_QHFOREACH_FAILED,     /* EHCI ERROR: sam_qh_foreach failed: */
  EHCI_TRACE1_SYSERR_INTR,          /* EHCI: Host System Error Interrupt */
  EHCI_TRACE1_USBERR_INTR,          /* EHCI: USB Error Interrupt (USBERRINT) Interrupt */
  EHCI_TRACE1_EPALLOC_FAILED,       /* EHCI ERROR: Failed to allocate EP info structure */
  EHCI_TRACE1_BADXFRTYPE,           /* EHCI ERROR: Support for transfer type not implemented */
  EHCI_TRACE1_HCHALTED_TIMEOUT,     /* EHCI ERROR: Timed out waiting for HCHalted */
  EHCI_TRACE1_QHPOOLALLOC_FAILED,   /* EHCI ERROR: Failed to allocate the QH pool */
  EHCI_TRACE1_QTDPOOLALLOC_FAILED,  /* EHCI ERROR: Failed to allocate the qTD pool */
  EHCI_TRACE1_PERFLALLOC_FAILED,    /* EHCI ERROR: Failed to allocate the periodic frame list */
  EHCI_TRACE1_RESET_FAILED,         /* EHCI ERROR: sam_reset failed */
  EHCI_TRACE1_RUN_FAILED,           /* EHCI ERROR: EHCI Failed to run */
  EHCI_TRACE1_IRQATTACH_FAILED,     /* EHCI ERROR: Failed to attach IRQ */

#ifdef HAVE_USBHOST_TRACE_VERBOSE
  EHCI_VTRACE1_PORTSC_CSC,          /* EHCI Connect Status Change */
  EHCI_VTRACE1_PORTSC_CONNALREADY,  /* EHCI Already connected */
  EHCI_VTRACE1_PORTSC_DISCALREADY,  /* EHCI Already disconnected */
  EHCI_VTRACE1_TOPHALF,             /* EHCI Interrupt top half */
  EHCI_VTRACE1_AAINTR,              /* EHCI Async Advance Interrupt */
  EHCI_VTRACE1_USBINTR,             /* EHCI USB Interrupt (USBINT) Interrupt */
  EHCI_VTRACE1_CLASSENUM,           /* EHCI Enumerate the device */
  EHCI_VTRACE1_ENUM_DISCONN,        /* EHCI Enumeration not connected */
  EHCI_VTRACE1_INITIALIZING,        /* EHCI Initializing EHCI Stack */
  EHCI_VTRACE1_HCCPARAMS,           /* EHCI HCCPARAMS */
  EHCI_VTRACE1_INIITIALIZED,        /* EHCI USB EHCI Initialized */
#endif
#endif

  __TRACE1_NSTRINGS,                /* Separates the format 1 from the format 2 strings */

#ifdef CONFIG_SAMA5_OHCI
  OHCI_TRACE2_BADTDSTATUS,          /* OHCI ERROR: RHport Bad TD completion status */
  OHCI_TRACE2_WHDTDSTATUS,          /* OHCI ERROR: WDH Bad TD completion status */
  OHCI_TRACE2_EP0ENQUEUE_FAILED,    /* OHCI ERROR: RHport Failed to enqueue EP0 */
  OHCI_TRACE2_EDENQUEUE_FAILED,     /* OHCI ERROR: Failed to queue ED for transfer type */
  OHCI_TRACE2_CLASSENUM_FAILED,     /* OHCI usbhost_enumerate() failed */

#ifdef HAVE_USBHOST_TRACE_VERBOSE
  OHCI_VTRACE2_EP0CONFIG,           /* OHCI EP0 configuration */
  OHCI_VTRACE2_INTERVAL,            /* OHCI interval */
  OHCI_VTRACE2_MININTERVAL,         /* OHCI MIN interval/offset */
  OHCI_VTRACE2_RHPORTST,            /* OHCI RHPORTST */
  OHCI_VTRACE2_CONNECTED,           /* OHCI RHPort connected */
  OHCI_VTRACE2_DISCONNECTED,        /* OHCI RHPort disconnected */
  OHCI_VTRACE2_WAKEUP,              /* OHCI RHPort connected wakeup */
  OHCI_VTRACE2_EP0CTRLED,           /* OHCI RHPort EP0 CTRL */
  OHCI_VTRACE2_EPALLOC,             /* OHCI EP CTRL */
  OHCI_VTRACE2_CTRLIN,              /* OHCI CTRLIN */
  OHCI_VTRACE2_CTRLOUT,             /* OHCI CTRLOUT */
  OHCI_VTRACE2_TRANSFER,            /* OHCI EP buflen */
  OHCI_VTRACE2_INITCONNECTED,       /* OHCI RHPort Device connected */
#ifdef CONFIG_USBHOST_HUB
  OHCI_VTRACE2_HUBWAKEUP,           /* EHCI Hub Port connected wakeup */
#endif
#endif
#endif

#ifdef CONFIG_SAMA5_EHCI
  EHCI_TRACE2_EPSTALLED,            /* EHCI EP Stalled */
  EHCI_TRACE2_EPIOERROR,            /* EHCI ERROR: EP TOKEN */
  EHCI_TRACE2_CLASSENUM_FAILED,     /* EHCI usbhost_enumerate() failed */

#ifdef HAVE_USBHOST_TRACE_VERBOSE
  EHCI_VTRACE2_EP0CONFIG,           /* EHCI EP0 configuration */
  EHCI_VTRACE2_ASYNCXFR,            /* EHCI Async transfer */
  EHCI_VTRACE2_INTRXFR,             /* EHCI Interrupt Transfer */
  EHCI_VTRACE2_IOCCHECK,            /* EHCI IOC */
  EHCI_VTRACE2_PORTSC,              /* EHCI PORTSC */
  EHCI_VTRACE2_PORTSC_CONNECTED,    /* EHCI RHPort connected */
  EHCI_VTRACE2_PORTSC_DISCONND,     /* EHCI RHport disconnected */
  EHCI_VTRACE2_MONWAKEUP,           /* EHCI RHPort connected wakeup */
  EHCI_VTRACE2_EPALLOC,             /* EHCI EPALLOC */
  EHCI_VTRACE2_CTRLINOUT,           /* EHCI CTRLIN/OUT */
  EHCI_VTRACE2_HCIVERSION,          /* EHCI HCIVERSION */
  EHCI_VTRACE2_HCSPARAMS,           /* EHCI HCSPARAMS */
#endif
#endif

  __TRACE2_NSTRINGS                 /* Total number of enumeration values */
};

#  define TRACE1_FIRST     ((int)__TRACE1_BASEVALUE + 1)
#  define TRACE1_INDEX(id) ((int)(id) - TRACE1_FIRST)
#  define TRACE1_NSTRINGS  TRACE1_INDEX(__TRACE1_NSTRINGS)

#  define TRACE2_FIRST     ((int)__TRACE1_NSTRINGS + 1)
#  define TRACE2_INDEX(id) ((int)(id) - TRACE2_FIRST)
#  define TRACE2_NSTRINGS  TRACE2_INDEX(__TRACE2_NSTRINGS)

#endif

/****************************************************************************
 * Public Data
 ****************************************************************************/

/****************************************************************************
 * Public Data
 ****************************************************************************/

#ifndef __ASSEMBLY__

#undef EXTERN
#if defined(__cplusplus)
#define EXTERN extern "C"
extern "C"
{
#else
#define EXTERN extern
#endif

/****************************************************************************
 * Public Functions Prototypes
 ****************************************************************************/

/****************************************************************************
 * Name: sam_ohci_initialize
 *
 * Description:
 *   Initialize USB OHCI host controller hardware.
 *
 * Input Parameters:
 *   controller -- If the device supports more than one USB OHCI interface,
 *     then this identifies which controller is being initializeed.
 *      Normally, this is just zero.
 *
 * Returned Value:
 *   And instance of the USB host interface.  The controlling task should
 *   use this interface to (1) call the wait() method to wait for a device
 *   to be connected, and (2) call the enumerate() method to bind the device
 *   to a class driver.
 *
 * Assumptions:
 * - This function should called in the initialization sequence in order
 *   to initialize the USB device functionality.
 * - Class drivers should be initialized prior to calling this function.
 *   Otherwise, there is a race condition if the device is already connected.
 *
 ****************************************************************************/

#ifdef CONFIG_SAMA5_OHCI
struct usbhost_connection_s;
struct usbhost_connection_s *sam_ohci_initialize(int controller);
#endif

/****************************************************************************
 * Name: sam_ohci_tophalf
 *
 * Description:
 *   OHCI "Top Half" interrupt handler.  If both EHCI and OHCI are enabled,
 *   then EHCI will manage the common UHPHS interrupt and will forward the
 *   interrupt event to this function.
 *
 ****************************************************************************/

#ifdef CONFIG_SAMA5_OHCI
int sam_ohci_tophalf(int irq, void *context, void *arg);
#endif

/****************************************************************************
 * Name: sam_ehci_initialize
 *
 * Description:
 *   Initialize USB EHCI host controller hardware.
 *
 * Input Parameters:
 *   controller -- If the device supports more than one EHCI interface, then
 *     this identifies which controller is being initializeed.  Normally,
 *     this is just zero.
 *
 * Returned Value:
 *   And instance of the USB host interface.  The controlling task should
 *   use this interface to (1) call the wait() method to wait for a device
 *   to be connected, and (2) call the enumerate() method to bind the device
 *   to a class driver.
 *
 * Assumptions:
 * - This function should called in the initialization sequence in order
 *   to initialize the USB device functionality.
 * - Class drivers should be initialized prior to calling this function.
 *   Otherwise, there is a race condition if the device is already connected.
 *
 ****************************************************************************/

#ifdef CONFIG_SAMA5_EHCI
struct usbhost_connection_s;
struct usbhost_connection_s *sam_ehci_initialize(int controller);
#endif

/****************************************************************************
 * Name: sam_usbhost_vbusdrive
 *
 * Description:
 *   Enable/disable driving of VBUS 5V output.  This function must be
 *   provided by each platform that implements the OHCI or EHCI host
 *   interface
 *
 * Input Parameters:
 *   rhport - Selects root hub port to be powered host interface.
 *            See SAM_RHPORT_*definitions above.
 *   enable - true: enable VBUS power; false: disable VBUS power
 *
 * Returned Value:
 *   None
 *
 ****************************************************************************/

void sam_usbhost_vbusdrive(int rhport, bool enable);

#undef EXTERN
#if defined(__cplusplus)
}
#endif

#endif /* __ASSEMBLY__ */
#endif /* CONFIG_USBHOST */
#endif /* __ARCH_ARM_SRC_SAMA5_SAM_USBHOST_H */