1130 lines
48 KiB
C
1130 lines
48 KiB
C
|
/***********************license start***************
|
||
|
* Copyright (c) 2003-2008 Cavium Networks (support@cavium.com). All rights
|
||
|
* reserved.
|
||
|
*
|
||
|
*
|
||
|
* Redistribution and use in source and binary forms, with or without
|
||
|
* modification, are permitted provided that the following conditions are
|
||
|
* met:
|
||
|
*
|
||
|
* * Redistributions of source code must retain the above copyright
|
||
|
* notice, this list of conditions and the following disclaimer.
|
||
|
*
|
||
|
* * Redistributions in binary form must reproduce the above
|
||
|
* copyright notice, this list of conditions and the following
|
||
|
* disclaimer in the documentation and/or other materials provided
|
||
|
* with the distribution.
|
||
|
*
|
||
|
* * Neither the name of Cavium Networks nor the names of
|
||
|
* its contributors may be used to endorse or promote products
|
||
|
* derived from this software without specific prior written
|
||
|
* permission.
|
||
|
*
|
||
|
* TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
|
||
|
* AND WITH ALL FAULTS AND CAVIUM NETWORKS MAKES NO PROMISES, REPRESENTATIONS
|
||
|
* OR WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH
|
||
|
* RESPECT TO THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY
|
||
|
* REPRESENTATION OR DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT
|
||
|
* DEFECTS, AND CAVIUM SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES
|
||
|
* OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR
|
||
|
* PURPOSE, LACK OF VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT, QUIET
|
||
|
* POSSESSION OR CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK ARISING OUT
|
||
|
* OF USE OR PERFORMANCE OF THE SOFTWARE LIES WITH YOU.
|
||
|
*
|
||
|
*
|
||
|
* For any questions regarding licensing please contact marketing@caviumnetworks.com
|
||
|
*
|
||
|
***********************license end**************************************/
|
||
|
|
||
|
/**
|
||
|
* @file
|
||
|
*
|
||
|
* "cvmx-usb.h" defines a set of low level USB functions to help
|
||
|
* developers create Octeon USB drivers for various operating
|
||
|
* systems. These functions provide a generic API to the Octeon
|
||
|
* USB blocks, hiding the internal hardware specific
|
||
|
* operations.
|
||
|
*
|
||
|
* At a high level the device driver needs to:
|
||
|
*
|
||
|
* -# Call cvmx_usb_get_num_ports() to get the number of
|
||
|
* supported ports.
|
||
|
* -# Call cvmx_usb_initialize() for each Octeon USB port.
|
||
|
* -# Enable the port using cvmx_usb_enable().
|
||
|
* -# Either periodically, or in an interrupt handler, call
|
||
|
* cvmx_usb_poll() to service USB events.
|
||
|
* -# Manage pipes using cvmx_usb_open_pipe() and
|
||
|
* cvmx_usb_close_pipe().
|
||
|
* -# Manage transfers using cvmx_usb_submit_*() and
|
||
|
* cvmx_usb_cancel*().
|
||
|
* -# Shutdown USB on unload using cvmx_usb_shutdown().
|
||
|
*
|
||
|
* To monitor USB status changes, the device driver must use
|
||
|
* cvmx_usb_register_callback() to register for events that it
|
||
|
* is interested in. Below are a few hints on successfully
|
||
|
* implementing a driver on top of this API.
|
||
|
*
|
||
|
* <h2>Initialization</h2>
|
||
|
*
|
||
|
* When a driver is first loaded, it is normally not necessary
|
||
|
* to bring up the USB port completely. Most operating systems
|
||
|
* expect to initialize and enable the port in two independent
|
||
|
* steps. Normally an operating system will probe hardware,
|
||
|
* initialize anything found, and then enable the hardware.
|
||
|
*
|
||
|
* In the probe phase you should:
|
||
|
* -# Use cvmx_usb_get_num_ports() to determine the number of
|
||
|
* USB port to be supported.
|
||
|
* -# Allocate space for a cvmx_usb_state_t structure for each
|
||
|
* port.
|
||
|
* -# Tell the operating system about each port
|
||
|
*
|
||
|
* In the initialization phase you should:
|
||
|
* -# Use cvmx_usb_initialize() on each port.
|
||
|
* -# Do not call cvmx_usb_enable(). This leaves the USB port in
|
||
|
* the disabled state until the operating system is ready.
|
||
|
*
|
||
|
* Finally, in the enable phase you should:
|
||
|
* -# Call cvmx_usb_enable() on the appropriate port.
|
||
|
* -# Note that some operating system use a RESET instead of an
|
||
|
* enable call. To implement RESET, you should call
|
||
|
* cvmx_usb_disable() followed by cvmx_usb_enable().
|
||
|
*
|
||
|
* <h2>Locking</h2>
|
||
|
*
|
||
|
* All of the functions in the cvmx-usb API assume exclusive
|
||
|
* access to the USB hardware and internal data structures. This
|
||
|
* means that the driver must provide locking as necessary.
|
||
|
*
|
||
|
* In the single CPU state it is normally enough to disable
|
||
|
* interrupts before every call to cvmx_usb*() and enable them
|
||
|
* again after the call is complete. Keep in mind that it is
|
||
|
* very common for the callback handlers to make additional
|
||
|
* calls into cvmx-usb, so the disable/enable must be protected
|
||
|
* against recursion. As an example, the Linux kernel
|
||
|
* local_irq_save() and local_irq_restore() are perfect for this
|
||
|
* in the non SMP case.
|
||
|
*
|
||
|
* In the SMP case, locking is more complicated. For SMP you not
|
||
|
* only need to disable interrupts on the local core, but also
|
||
|
* take a lock to make sure that another core cannot call
|
||
|
* cvmx-usb.
|
||
|
*
|
||
|
* <h2>Port callback</h2>
|
||
|
*
|
||
|
* The port callback prototype needs to look as follows:
|
||
|
*
|
||
|
* void port_callback(cvmx_usb_state_t *usb,
|
||
|
* cvmx_usb_callback_t reason,
|
||
|
* cvmx_usb_complete_t status,
|
||
|
* int pipe_handle,
|
||
|
* int submit_handle,
|
||
|
* int bytes_transferred,
|
||
|
* void *user_data);
|
||
|
* - @b usb is the cvmx_usb_state_t for the port.
|
||
|
* - @b reason will always be
|
||
|
* CVMX_USB_CALLBACK_PORT_CHANGED.
|
||
|
* - @b status will always be CVMX_USB_COMPLETE_SUCCESS.
|
||
|
* - @b pipe_handle will always be -1.
|
||
|
* - @b submit_handle will always be -1.
|
||
|
* - @b bytes_transferred will always be 0.
|
||
|
* - @b user_data is the void pointer originally passed along
|
||
|
* with the callback. Use this for any state information you
|
||
|
* need.
|
||
|
*
|
||
|
* The port callback will be called whenever the user plugs /
|
||
|
* unplugs a device from the port. It will not be called when a
|
||
|
* device is plugged / unplugged from a hub connected to the
|
||
|
* root port. Normally all the callback needs to do is tell the
|
||
|
* operating system to poll the root hub for status. Under
|
||
|
* Linux, this is performed by calling usb_hcd_poll_rh_status().
|
||
|
* In the Linux driver we use @b user_data. to pass around the
|
||
|
* Linux "hcd" structure. Once the port callback completes,
|
||
|
* Linux automatically calls octeon_usb_hub_status_data() which
|
||
|
* uses cvmx_usb_get_status() to determine the root port status.
|
||
|
*
|
||
|
* <h2>Complete callback</h2>
|
||
|
*
|
||
|
* The completion callback prototype needs to look as follows:
|
||
|
*
|
||
|
* void complete_callback(cvmx_usb_state_t *usb,
|
||
|
* cvmx_usb_callback_t reason,
|
||
|
* cvmx_usb_complete_t status,
|
||
|
* int pipe_handle,
|
||
|
* int submit_handle,
|
||
|
* int bytes_transferred,
|
||
|
* void *user_data);
|
||
|
* - @b usb is the cvmx_usb_state_t for the port.
|
||
|
* - @b reason will always be
|
||
|
* CVMX_USB_CALLBACK_TRANSFER_COMPLETE.
|
||
|
* - @b status will be one of the cvmx_usb_complete_t
|
||
|
* enumerations.
|
||
|
* - @b pipe_handle is the handle to the pipe the transaction
|
||
|
* was originally submitted on.
|
||
|
* - @b submit_handle is the handle returned by the original
|
||
|
* cvmx_usb_submit_* call.
|
||
|
* - @b bytes_transferred is the number of bytes successfully
|
||
|
* transferred in the transaction. This will be zero on most
|
||
|
* error conditions.
|
||
|
* - @b user_data is the void pointer originally passed along
|
||
|
* with the callback. Use this for any state information you
|
||
|
* need. For example, the Linux "urb" is stored in here in the
|
||
|
* Linux driver.
|
||
|
*
|
||
|
* In general your callback handler should use @b status and @b
|
||
|
* bytes_transferred to tell the operating system the how the
|
||
|
* transaction completed. Normally the pipe is not changed in
|
||
|
* this callback.
|
||
|
*
|
||
|
* <h2>Canceling transactions</h2>
|
||
|
*
|
||
|
* When a transaction is cancelled using cvmx_usb_cancel*(), the
|
||
|
* actual length of time until the complete callback is called
|
||
|
* can vary greatly. It may be called before cvmx_usb_cancel*()
|
||
|
* returns, or it may be called a number of usb frames in the
|
||
|
* future once the hardware frees the transaction. In either of
|
||
|
* these cases, the complete handler will receive
|
||
|
* CVMX_USB_COMPLETE_CANCEL.
|
||
|
*
|
||
|
* <h2>Handling pipes</h2>
|
||
|
*
|
||
|
* USB "pipes" is a software construct created by this API to
|
||
|
* enable the ordering of usb transactions to a device endpoint.
|
||
|
* Octeon's underlying hardware doesn't have any concept
|
||
|
* equivalent to "pipes". The hardware instead has eight
|
||
|
* channels that can be used simultaneously to have up to eight
|
||
|
* transaction in process at the same time. In order to maintain
|
||
|
* ordering in a pipe, the transactions for a pipe will only be
|
||
|
* active in one hardware channel at a time. From an API user's
|
||
|
* perspective, this doesn't matter but it can be helpful to
|
||
|
* keep this in mind when you are probing hardware while
|
||
|
* debugging.
|
||
|
*
|
||
|
* Also keep in mind that usb transactions contain state
|
||
|
* information about the previous transaction to the same
|
||
|
* endpoint. Each transaction has a PID toggle that changes 0/1
|
||
|
* between each sub packet. This is maintained in the pipe data
|
||
|
* structures. For this reason, you generally cannot create and
|
||
|
* destroy a pipe for every transaction. A sequence of
|
||
|
* transaction to the same endpoint must use the same pipe.
|
||
|
*
|
||
|
* <h2>Root Hub</h2>
|
||
|
*
|
||
|
* Some operating systems view the usb root port as a normal usb
|
||
|
* hub. These systems attempt to control the root hub with
|
||
|
* messages similar to the usb 2.0 spec for hub control and
|
||
|
* status. For these systems it may be necessary to write
|
||
|
* function to decode standard usb control messages into
|
||
|
* equivalent cvmx-usb API calls. As an example, the following
|
||
|
* code is used under Linux for some of the basic hub control
|
||
|
* messages.
|
||
|
*
|
||
|
* @code
|
||
|
* static int octeon_usb_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, u16 wIndex, char *buf, u16 wLength)
|
||
|
* {
|
||
|
* cvmx_usb_state_t *usb = (cvmx_usb_state_t *)hcd->hcd_priv;
|
||
|
* cvmx_usb_port_status_t usb_port_status;
|
||
|
* int port_status;
|
||
|
* struct usb_hub_descriptor *desc;
|
||
|
* unsigned long flags;
|
||
|
*
|
||
|
* switch (typeReq)
|
||
|
* {
|
||
|
* case ClearHubFeature:
|
||
|
* DEBUG_ROOT_HUB("OcteonUSB: ClearHubFeature\n");
|
||
|
* switch (wValue)
|
||
|
* {
|
||
|
* case C_HUB_LOCAL_POWER:
|
||
|
* case C_HUB_OVER_CURRENT:
|
||
|
* // Nothing required here
|
||
|
* break;
|
||
|
* default:
|
||
|
* return -EINVAL;
|
||
|
* }
|
||
|
* break;
|
||
|
* case ClearPortFeature:
|
||
|
* DEBUG_ROOT_HUB("OcteonUSB: ClearPortFeature");
|
||
|
* if (wIndex != 1)
|
||
|
* {
|
||
|
* DEBUG_ROOT_HUB(" INVALID\n");
|
||
|
* return -EINVAL;
|
||
|
* }
|
||
|
*
|
||
|
* switch (wValue)
|
||
|
* {
|
||
|
* case USB_PORT_FEAT_ENABLE:
|
||
|
* DEBUG_ROOT_HUB(" ENABLE");
|
||
|
* local_irq_save(flags);
|
||
|
* cvmx_usb_disable(usb);
|
||
|
* local_irq_restore(flags);
|
||
|
* break;
|
||
|
* case USB_PORT_FEAT_SUSPEND:
|
||
|
* DEBUG_ROOT_HUB(" SUSPEND");
|
||
|
* // Not supported on Octeon
|
||
|
* break;
|
||
|
* case USB_PORT_FEAT_POWER:
|
||
|
* DEBUG_ROOT_HUB(" POWER");
|
||
|
* // Not supported on Octeon
|
||
|
* break;
|
||
|
* case USB_PORT_FEAT_INDICATOR:
|
||
|
* DEBUG_ROOT_HUB(" INDICATOR");
|
||
|
* // Port inidicator not supported
|
||
|
* break;
|
||
|
* case USB_PORT_FEAT_C_CONNECTION:
|
||
|
* DEBUG_ROOT_HUB(" C_CONNECTION");
|
||
|
* // Clears drivers internal connect status change flag
|
||
|
* cvmx_usb_set_status(usb, cvmx_usb_get_status(usb));
|
||
|
* break;
|
||
|
* case USB_PORT_FEAT_C_RESET:
|
||
|
* DEBUG_ROOT_HUB(" C_RESET");
|
||
|
* // Clears the driver's internal Port Reset Change flag
|
||
|
* cvmx_usb_set_status(usb, cvmx_usb_get_status(usb));
|
||
|
* break;
|
||
|
* case USB_PORT_FEAT_C_ENABLE:
|
||
|
* DEBUG_ROOT_HUB(" C_ENABLE");
|
||
|
* // Clears the driver's internal Port Enable/Disable Change flag
|
||
|
* cvmx_usb_set_status(usb, cvmx_usb_get_status(usb));
|
||
|
* break;
|
||
|
* case USB_PORT_FEAT_C_SUSPEND:
|
||
|
* DEBUG_ROOT_HUB(" C_SUSPEND");
|
||
|
* // Clears the driver's internal Port Suspend Change flag,
|
||
|
* which is set when resume signaling on the host port is
|
||
|
* complete
|
||
|
* break;
|
||
|
* case USB_PORT_FEAT_C_OVER_CURRENT:
|
||
|
* DEBUG_ROOT_HUB(" C_OVER_CURRENT");
|
||
|
* // Clears the driver's overcurrent Change flag
|
||
|
* cvmx_usb_set_status(usb, cvmx_usb_get_status(usb));
|
||
|
* break;
|
||
|
* default:
|
||
|
* DEBUG_ROOT_HUB(" UNKNOWN\n");
|
||
|
* return -EINVAL;
|
||
|
* }
|
||
|
* DEBUG_ROOT_HUB("\n");
|
||
|
* break;
|
||
|
* case GetHubDescriptor:
|
||
|
* DEBUG_ROOT_HUB("OcteonUSB: GetHubDescriptor\n");
|
||
|
* desc = (struct usb_hub_descriptor *)buf;
|
||
|
* desc->bDescLength = 9;
|
||
|
* desc->bDescriptorType = 0x29;
|
||
|
* desc->bNbrPorts = 1;
|
||
|
* desc->wHubCharacteristics = 0x08;
|
||
|
* desc->bPwrOn2PwrGood = 1;
|
||
|
* desc->bHubContrCurrent = 0;
|
||
|
* desc->bitmap[0] = 0;
|
||
|
* desc->bitmap[1] = 0xff;
|
||
|
* break;
|
||
|
* case GetHubStatus:
|
||
|
* DEBUG_ROOT_HUB("OcteonUSB: GetHubStatus\n");
|
||
|
* *(__le32 *)buf = 0;
|
||
|
* break;
|
||
|
* case GetPortStatus:
|
||
|
* DEBUG_ROOT_HUB("OcteonUSB: GetPortStatus");
|
||
|
* if (wIndex != 1)
|
||
|
* {
|
||
|
* DEBUG_ROOT_HUB(" INVALID\n");
|
||
|
* return -EINVAL;
|
||
|
* }
|
||
|
*
|
||
|
* usb_port_status = cvmx_usb_get_status(usb);
|
||
|
* port_status = 0;
|
||
|
*
|
||
|
* if (usb_port_status.connect_change)
|
||
|
* {
|
||
|
* port_status |= (1 << USB_PORT_FEAT_C_CONNECTION);
|
||
|
* DEBUG_ROOT_HUB(" C_CONNECTION");
|
||
|
* }
|
||
|
*
|
||
|
* if (usb_port_status.port_enabled)
|
||
|
* {
|
||
|
* port_status |= (1 << USB_PORT_FEAT_C_ENABLE);
|
||
|
* DEBUG_ROOT_HUB(" C_ENABLE");
|
||
|
* }
|
||
|
*
|
||
|
* if (usb_port_status.connected)
|
||
|
* {
|
||
|
* port_status |= (1 << USB_PORT_FEAT_CONNECTION);
|
||
|
* DEBUG_ROOT_HUB(" CONNECTION");
|
||
|
* }
|
||
|
*
|
||
|
* if (usb_port_status.port_enabled)
|
||
|
* {
|
||
|
* port_status |= (1 << USB_PORT_FEAT_ENABLE);
|
||
|
* DEBUG_ROOT_HUB(" ENABLE");
|
||
|
* }
|
||
|
*
|
||
|
* if (usb_port_status.port_over_current)
|
||
|
* {
|
||
|
* port_status |= (1 << USB_PORT_FEAT_OVER_CURRENT);
|
||
|
* DEBUG_ROOT_HUB(" OVER_CURRENT");
|
||
|
* }
|
||
|
*
|
||
|
* if (usb_port_status.port_powered)
|
||
|
* {
|
||
|
* port_status |= (1 << USB_PORT_FEAT_POWER);
|
||
|
* DEBUG_ROOT_HUB(" POWER");
|
||
|
* }
|
||
|
*
|
||
|
* if (usb_port_status.port_speed == CVMX_USB_SPEED_HIGH)
|
||
|
* {
|
||
|
* port_status |= (1 << USB_PORT_FEAT_HIGHSPEED);
|
||
|
* DEBUG_ROOT_HUB(" HIGHSPEED");
|
||
|
* }
|
||
|
* else if (usb_port_status.port_speed == CVMX_USB_SPEED_LOW)
|
||
|
* {
|
||
|
* port_status |= (1 << USB_PORT_FEAT_LOWSPEED);
|
||
|
* DEBUG_ROOT_HUB(" LOWSPEED");
|
||
|
* }
|
||
|
*
|
||
|
* *((__le32 *)buf) = cpu_to_le32(port_status);
|
||
|
* DEBUG_ROOT_HUB("\n");
|
||
|
* break;
|
||
|
* case SetHubFeature:
|
||
|
* DEBUG_ROOT_HUB("OcteonUSB: SetHubFeature\n");
|
||
|
* // No HUB features supported
|
||
|
* break;
|
||
|
* case SetPortFeature:
|
||
|
* DEBUG_ROOT_HUB("OcteonUSB: SetPortFeature");
|
||
|
* if (wIndex != 1)
|
||
|
* {
|
||
|
* DEBUG_ROOT_HUB(" INVALID\n");
|
||
|
* return -EINVAL;
|
||
|
* }
|
||
|
*
|
||
|
* switch (wValue)
|
||
|
* {
|
||
|
* case USB_PORT_FEAT_SUSPEND:
|
||
|
* DEBUG_ROOT_HUB(" SUSPEND\n");
|
||
|
* return -EINVAL;
|
||
|
* case USB_PORT_FEAT_POWER:
|
||
|
* DEBUG_ROOT_HUB(" POWER\n");
|
||
|
* return -EINVAL;
|
||
|
* case USB_PORT_FEAT_RESET:
|
||
|
* DEBUG_ROOT_HUB(" RESET\n");
|
||
|
* local_irq_save(flags);
|
||
|
* cvmx_usb_disable(usb);
|
||
|
* if (cvmx_usb_enable(usb))
|
||
|
* DEBUG_ERROR("Failed to enable the port\n");
|
||
|
* local_irq_restore(flags);
|
||
|
* return 0;
|
||
|
* case USB_PORT_FEAT_INDICATOR:
|
||
|
* DEBUG_ROOT_HUB(" INDICATOR\n");
|
||
|
* // Not supported
|
||
|
* break;
|
||
|
* default:
|
||
|
* DEBUG_ROOT_HUB(" UNKNOWN\n");
|
||
|
* return -EINVAL;
|
||
|
* }
|
||
|
* break;
|
||
|
* default:
|
||
|
* DEBUG_ROOT_HUB("OcteonUSB: Unknown root hub request\n");
|
||
|
* return -EINVAL;
|
||
|
* }
|
||
|
* return 0;
|
||
|
* }
|
||
|
* @endcode
|
||
|
*
|
||
|
* <h2>Interrupts</h2>
|
||
|
*
|
||
|
* If you plan on using usb interrupts, cvmx_usb_poll() must be
|
||
|
* called on every usb interrupt. It will read the usb state,
|
||
|
* call any needed callbacks, and schedule transactions as
|
||
|
* needed. Your device driver needs only to hookup an interrupt
|
||
|
* handler and call cvmx_usb_poll(). Octeon's usb port 0 causes
|
||
|
* CIU bit CIU_INT*_SUM0[USB] to be set (bit 56). For port 1,
|
||
|
* CIU bit CIU_INT_SUM1[USB1] is set (bit 17). How these bits
|
||
|
* are turned into interrupt numbers is operating system
|
||
|
* specific. For Linux, there are the convenient defines
|
||
|
* OCTEON_IRQ_USB0 and OCTEON_IRQ_USB1 for the IRQ numbers.
|
||
|
*
|
||
|
* If you aren't using interrupts, simple call cvmx_usb_poll()
|
||
|
* in your main processing loop.
|
||
|
*
|
||
|
* <hr>$Revision: 32636 $<hr>
|
||
|
*/
|
||
|
|
||
|
#ifndef __CVMX_USB_H__
|
||
|
#define __CVMX_USB_H__
|
||
|
|
||
|
#ifdef __cplusplus
|
||
|
extern "C" {
|
||
|
#endif
|
||
|
|
||
|
/**
|
||
|
* Enumerations representing the status of function calls.
|
||
|
*/
|
||
|
typedef enum
|
||
|
{
|
||
|
CVMX_USB_SUCCESS = 0, /**< There were no errors */
|
||
|
CVMX_USB_INVALID_PARAM = -1, /**< A parameter to the function was invalid */
|
||
|
CVMX_USB_NO_MEMORY = -2, /**< Insufficient resources were available for the request */
|
||
|
CVMX_USB_BUSY = -3, /**< The resource is busy and cannot service the request */
|
||
|
CVMX_USB_TIMEOUT = -4, /**< Waiting for an action timed out */
|
||
|
CVMX_USB_INCORRECT_MODE = -5, /**< The function call doesn't work in the current USB
|
||
|
mode. This happens when host only functions are
|
||
|
called in device mode or vice versa */
|
||
|
} cvmx_usb_status_t;
|
||
|
|
||
|
/**
|
||
|
* Enumerations representing the possible USB device speeds
|
||
|
*/
|
||
|
typedef enum
|
||
|
{
|
||
|
CVMX_USB_SPEED_HIGH = 0, /**< Device is operation at 480Mbps */
|
||
|
CVMX_USB_SPEED_FULL = 1, /**< Device is operation at 12Mbps */
|
||
|
CVMX_USB_SPEED_LOW = 2, /**< Device is operation at 1.5Mbps */
|
||
|
} cvmx_usb_speed_t;
|
||
|
|
||
|
/**
|
||
|
* Enumeration representing the possible USB transfer types.
|
||
|
*/
|
||
|
typedef enum
|
||
|
{
|
||
|
CVMX_USB_TRANSFER_CONTROL = 0, /**< USB transfer type control for hub and status transfers */
|
||
|
CVMX_USB_TRANSFER_ISOCHRONOUS = 1, /**< USB transfer type isochronous for low priority periodic transfers */
|
||
|
CVMX_USB_TRANSFER_BULK = 2, /**< USB transfer type bulk for large low priority transfers */
|
||
|
CVMX_USB_TRANSFER_INTERRUPT = 3, /**< USB transfer type interrupt for high priority periodic transfers */
|
||
|
} cvmx_usb_transfer_t;
|
||
|
|
||
|
/**
|
||
|
* Enumeration of the transfer directions
|
||
|
*/
|
||
|
typedef enum
|
||
|
{
|
||
|
CVMX_USB_DIRECTION_OUT, /**< Data is transferring from Octeon to the device/host */
|
||
|
CVMX_USB_DIRECTION_IN, /**< Data is transferring from the device/host to Octeon */
|
||
|
} cvmx_usb_direction_t;
|
||
|
|
||
|
/**
|
||
|
* Enumeration of all possible status codes passed to callback
|
||
|
* functions.
|
||
|
*/
|
||
|
typedef enum
|
||
|
{
|
||
|
CVMX_USB_COMPLETE_SUCCESS, /**< The transaction / operation finished without any errors */
|
||
|
CVMX_USB_COMPLETE_SHORT, /**< FIXME: This is currently not implemented */
|
||
|
CVMX_USB_COMPLETE_CANCEL, /**< The transaction was canceled while in flight by a user call to cvmx_usb_cancel* */
|
||
|
CVMX_USB_COMPLETE_ERROR, /**< The transaction aborted with an unexpected error status */
|
||
|
CVMX_USB_COMPLETE_STALL, /**< The transaction received a USB STALL response from the device */
|
||
|
CVMX_USB_COMPLETE_XACTERR, /**< The transaction failed with an error from the device even after a number of retries */
|
||
|
CVMX_USB_COMPLETE_DATATGLERR, /**< The transaction failed with a data toggle error even after a number of retries */
|
||
|
CVMX_USB_COMPLETE_BABBLEERR, /**< The transaction failed with a babble error */
|
||
|
CVMX_USB_COMPLETE_FRAMEERR, /**< The transaction failed with a frame error even after a number of retries */
|
||
|
} cvmx_usb_complete_t;
|
||
|
|
||
|
/**
|
||
|
* Structure returned containing the USB port status information.
|
||
|
*/
|
||
|
typedef struct
|
||
|
{
|
||
|
uint32_t reserved : 25;
|
||
|
uint32_t port_enabled : 1; /**< 1 = Usb port is enabled, 0 = disabled */
|
||
|
uint32_t port_over_current : 1; /**< 1 = Over current detected, 0 = Over current not detected. Octeon doesn't support over current detection */
|
||
|
uint32_t port_powered : 1; /**< 1 = Port power is being supplied to the device, 0 = power is off. Octeon doesn't support turning port power off */
|
||
|
cvmx_usb_speed_t port_speed : 2; /**< Current port speed */
|
||
|
uint32_t connected : 1; /**< 1 = A device is connected to the port, 0 = No device is connected */
|
||
|
uint32_t connect_change : 1; /**< 1 = Device connected state changed since the last set status call */
|
||
|
} cvmx_usb_port_status_t;
|
||
|
|
||
|
/**
|
||
|
* This is the structure of a Control packet header
|
||
|
*/
|
||
|
typedef union
|
||
|
{
|
||
|
uint64_t u64;
|
||
|
struct
|
||
|
{
|
||
|
uint64_t request_type : 8; /**< Bit 7 tells the direction: 1=IN, 0=OUT */
|
||
|
uint64_t request : 8; /**< The standard usb request to make */
|
||
|
uint64_t value : 16; /**< Value parameter for the request in little endian format */
|
||
|
uint64_t index : 16; /**< Index for the request in little endian format */
|
||
|
uint64_t length : 16; /**< Length of the data associated with this request in little endian format */
|
||
|
} s;
|
||
|
} cvmx_usb_control_header_t;
|
||
|
|
||
|
/**
|
||
|
* Descriptor for Isochronous packets
|
||
|
*/
|
||
|
typedef struct
|
||
|
{
|
||
|
int offset; /**< This is the offset in bytes into the main buffer where this data is stored */
|
||
|
int length; /**< This is the length in bytes of the data */
|
||
|
cvmx_usb_complete_t status; /**< This is the status of this individual packet transfer */
|
||
|
} cvmx_usb_iso_packet_t;
|
||
|
|
||
|
/**
|
||
|
* Possible callback reasons for the USB API.
|
||
|
*/
|
||
|
typedef enum
|
||
|
{
|
||
|
CVMX_USB_CALLBACK_TRANSFER_COMPLETE,
|
||
|
/**< A callback of this type is called when a submitted transfer
|
||
|
completes. The completion callback will be called even if the
|
||
|
transfer fails or is canceled. The status parameter will
|
||
|
contain details of why he callback was called. */
|
||
|
CVMX_USB_CALLBACK_PORT_CHANGED, /**< The status of the port changed. For example, someone may have
|
||
|
plugged a device in. The status parameter contains
|
||
|
CVMX_USB_COMPLETE_SUCCESS. Use cvmx_usb_get_status() to get
|
||
|
the new port status. */
|
||
|
CVMX_USB_CALLBACK_DEVICE_SETUP, /**< This is called in device mode when a control channels receives
|
||
|
a setup header */
|
||
|
__CVMX_USB_CALLBACK_END /**< Do not use. Used internally for array bounds */
|
||
|
} cvmx_usb_callback_t;
|
||
|
|
||
|
/**
|
||
|
* USB state internal data. The contents of this structure
|
||
|
* may change in future SDKs. No data in it should be referenced
|
||
|
* by user's of this API.
|
||
|
*/
|
||
|
typedef struct
|
||
|
{
|
||
|
char data[65536];
|
||
|
} cvmx_usb_state_t;
|
||
|
|
||
|
/**
|
||
|
* USB callback functions are always of the following type.
|
||
|
* The parameters are as follows:
|
||
|
* - state = USB device state populated by
|
||
|
* cvmx_usb_initialize().
|
||
|
* - reason = The cvmx_usb_callback_t used to register
|
||
|
* the callback.
|
||
|
* - status = The cvmx_usb_complete_t representing the
|
||
|
* status code of a transaction.
|
||
|
* - pipe_handle = The Pipe that caused this callback, or
|
||
|
* -1 if this callback wasn't associated with a pipe.
|
||
|
* - submit_handle = Transfer submit handle causing this
|
||
|
* callback, or -1 if this callback wasn't associated
|
||
|
* with a transfer.
|
||
|
* - Actual number of bytes transfer.
|
||
|
* - user_data = The user pointer supplied to the
|
||
|
* function cvmx_usb_submit() or
|
||
|
* cvmx_usb_register_callback() */
|
||
|
typedef void (*cvmx_usb_callback_func_t)(cvmx_usb_state_t *state,
|
||
|
cvmx_usb_callback_t reason,
|
||
|
cvmx_usb_complete_t status,
|
||
|
int pipe_handle, int submit_handle,
|
||
|
int bytes_transferred, void *user_data);
|
||
|
|
||
|
/**
|
||
|
* Flags to pass the initialization function.
|
||
|
*/
|
||
|
typedef enum
|
||
|
{
|
||
|
CVMX_USB_INITIALIZE_FLAGS_CLOCK_XO_XI = 1<<0, /**< The USB port uses a 12MHz crystal as clock source
|
||
|
at USB_XO and USB_XI. */
|
||
|
CVMX_USB_INITIALIZE_FLAGS_CLOCK_XO_GND = 1<<1, /**< The USB port uses 12/24/48MHz 2.5V board clock
|
||
|
source at USB_XO. USB_XI should be tied to GND.*/
|
||
|
CVMX_USB_INITIALIZE_FLAGS_CLOCK_AUTO = 0, /**< Automatically determine clock type based on function
|
||
|
in cvmx-helper-board.c. */
|
||
|
CVMX_USB_INITIALIZE_FLAGS_DEVICE_MODE = 1<<2, /**< Program the USB port for device mode instead of host mode */
|
||
|
CVMX_USB_INITIALIZE_FLAGS_CLOCK_MHZ_MASK = 3<<3, /**< Mask for clock speed field */
|
||
|
CVMX_USB_INITIALIZE_FLAGS_CLOCK_12MHZ = 1<<3, /**< Speed of reference clock or crystal */
|
||
|
CVMX_USB_INITIALIZE_FLAGS_CLOCK_24MHZ = 2<<3, /**< Speed of reference clock */
|
||
|
CVMX_USB_INITIALIZE_FLAGS_CLOCK_48MHZ = 3<<3, /**< Speed of reference clock */
|
||
|
/* Bits 3-4 used to encode the clock frequency */
|
||
|
CVMX_USB_INITIALIZE_FLAGS_DEBUG_TRANSFERS = 1<<16, /**< Enable extra console output for debugging USB transfers */
|
||
|
CVMX_USB_INITIALIZE_FLAGS_DEBUG_CALLBACKS = 1<<17, /**< Enable extra console output for debugging USB callbacks */
|
||
|
CVMX_USB_INITIALIZE_FLAGS_DEBUG_INFO = 1<<18, /**< Enable extra console output for USB informational data */
|
||
|
CVMX_USB_INITIALIZE_FLAGS_DEBUG_CALLS = 1<<19, /**< Enable extra console output for every function call */
|
||
|
CVMX_USB_INITIALIZE_FLAGS_DEBUG_CSRS = 1<<20, /**< Enable extra console output for every CSR access */
|
||
|
CVMX_USB_INITIALIZE_FLAGS_DEBUG_ALL = ((CVMX_USB_INITIALIZE_FLAGS_DEBUG_CSRS<<1)-1) - (CVMX_USB_INITIALIZE_FLAGS_DEBUG_TRANSFERS-1),
|
||
|
} cvmx_usb_initialize_flags_t;
|
||
|
|
||
|
/**
|
||
|
* Flags for passing when a pipe is created. Currently no flags
|
||
|
* need to be passed.
|
||
|
*/
|
||
|
typedef enum
|
||
|
{
|
||
|
CVMX_USB_PIPE_FLAGS_DEBUG_TRANSFERS = 1<<15,/**< Used to display CVMX_USB_INITIALIZE_FLAGS_DEBUG_TRANSFERS for a specific pipe only */
|
||
|
__CVMX_USB_PIPE_FLAGS_OPEN = 1<<16, /**< Used internally to determine if a pipe is open. Do not use */
|
||
|
__CVMX_USB_PIPE_FLAGS_SCHEDULED = 1<<17, /**< Used internally to determine if a pipe is actively using hardware. Do not use */
|
||
|
__CVMX_USB_PIPE_FLAGS_NEED_PING = 1<<18, /**< Used internally to determine if a high speed pipe is in the ping state. Do not use */
|
||
|
} cvmx_usb_pipe_flags_t;
|
||
|
|
||
|
/**
|
||
|
* Return the number of USB ports supported by this Octeon
|
||
|
* chip. If the chip doesn't support USB, or is not supported
|
||
|
* by this API, a zero will be returned. Most Octeon chips
|
||
|
* support one usb port, but some support two ports.
|
||
|
* cvmx_usb_initialize() must be called on independent
|
||
|
* cvmx_usb_state_t structures.
|
||
|
*
|
||
|
* @return Number of port, zero if usb isn't supported
|
||
|
*/
|
||
|
extern int cvmx_usb_get_num_ports(void);
|
||
|
|
||
|
/**
|
||
|
* Initialize a USB port for use. This must be called before any
|
||
|
* other access to the Octeon USB port is made. The port starts
|
||
|
* off in the disabled state.
|
||
|
*
|
||
|
* @param state Pointer to an empty cvmx_usb_state_t structure
|
||
|
* that will be populated by the initialize call.
|
||
|
* This structure is then passed to all other USB
|
||
|
* functions.
|
||
|
* @param usb_port_number
|
||
|
* Which Octeon USB port to initialize.
|
||
|
* @param flags Flags to control hardware initialization. See
|
||
|
* cvmx_usb_initialize_flags_t for the flag
|
||
|
* definitions. Some flags are mandatory.
|
||
|
*
|
||
|
* @return CVMX_USB_SUCCESS or a negative error code defined in
|
||
|
* cvmx_usb_status_t.
|
||
|
*/
|
||
|
extern cvmx_usb_status_t cvmx_usb_initialize(cvmx_usb_state_t *state,
|
||
|
int usb_port_number,
|
||
|
cvmx_usb_initialize_flags_t flags);
|
||
|
|
||
|
/**
|
||
|
* Shutdown a USB port after a call to cvmx_usb_initialize().
|
||
|
* The port should be disabled with all pipes closed when this
|
||
|
* function is called.
|
||
|
*
|
||
|
* @param state USB device state populated by
|
||
|
* cvmx_usb_initialize().
|
||
|
*
|
||
|
* @return CVMX_USB_SUCCESS or a negative error code defined in
|
||
|
* cvmx_usb_status_t.
|
||
|
*/
|
||
|
extern cvmx_usb_status_t cvmx_usb_shutdown(cvmx_usb_state_t *state);
|
||
|
|
||
|
/**
|
||
|
* Enable a USB port. After this call succeeds, the USB port is
|
||
|
* online and servicing requests.
|
||
|
*
|
||
|
* @param state USB device state populated by
|
||
|
* cvmx_usb_initialize().
|
||
|
*
|
||
|
* @return CVMX_USB_SUCCESS or a negative error code defined in
|
||
|
* cvmx_usb_status_t.
|
||
|
*/
|
||
|
extern cvmx_usb_status_t cvmx_usb_enable(cvmx_usb_state_t *state);
|
||
|
|
||
|
/**
|
||
|
* Disable a USB port. After this call the USB port will not
|
||
|
* generate data transfers and will not generate events.
|
||
|
* Transactions in process will fail and call their
|
||
|
* associated callbacks.
|
||
|
*
|
||
|
* @param state USB device state populated by
|
||
|
* cvmx_usb_initialize().
|
||
|
*
|
||
|
* @return CVMX_USB_SUCCESS or a negative error code defined in
|
||
|
* cvmx_usb_status_t.
|
||
|
*/
|
||
|
extern cvmx_usb_status_t cvmx_usb_disable(cvmx_usb_state_t *state);
|
||
|
|
||
|
/**
|
||
|
* Get the current state of the USB port. Use this call to
|
||
|
* determine if the usb port has anything connected, is enabled,
|
||
|
* or has some sort of error condition. The return value of this
|
||
|
* call has "changed" bits to signal of the value of some fields
|
||
|
* have changed between calls. These "changed" fields are based
|
||
|
* on the last call to cvmx_usb_set_status(). In order to clear
|
||
|
* them, you must update the status through cvmx_usb_set_status().
|
||
|
*
|
||
|
* @param state USB device state populated by
|
||
|
* cvmx_usb_initialize().
|
||
|
*
|
||
|
* @return Port status information
|
||
|
*/
|
||
|
extern cvmx_usb_port_status_t cvmx_usb_get_status(cvmx_usb_state_t *state);
|
||
|
|
||
|
/**
|
||
|
* Set the current state of the USB port. The status is used as
|
||
|
* a reference for the "changed" bits returned by
|
||
|
* cvmx_usb_get_status(). Other than serving as a reference, the
|
||
|
* status passed to this function is not used. No fields can be
|
||
|
* changed through this call.
|
||
|
*
|
||
|
* @param state USB device state populated by
|
||
|
* cvmx_usb_initialize().
|
||
|
* @param port_status
|
||
|
* Port status to set, most like returned by cvmx_usb_get_status()
|
||
|
*/
|
||
|
extern void cvmx_usb_set_status(cvmx_usb_state_t *state, cvmx_usb_port_status_t port_status);
|
||
|
|
||
|
/**
|
||
|
* Open a virtual pipe between the host and a USB device. A pipe
|
||
|
* must be opened before data can be transferred between a device
|
||
|
* and Octeon.
|
||
|
*
|
||
|
* @param state USB device state populated by
|
||
|
* cvmx_usb_initialize().
|
||
|
* @param flags Optional pipe flags defined in
|
||
|
* cvmx_usb_pipe_flags_t.
|
||
|
* @param device_addr
|
||
|
* USB device address to open the pipe to
|
||
|
* (0-127).
|
||
|
* @param endpoint_num
|
||
|
* USB endpoint number to open the pipe to
|
||
|
* (0-15).
|
||
|
* @param device_speed
|
||
|
* The speed of the device the pipe is going
|
||
|
* to. This must match the device's speed,
|
||
|
* which may be different than the port speed.
|
||
|
* @param max_packet The maximum packet length the device can
|
||
|
* transmit/receive (low speed=0-8, full
|
||
|
* speed=0-1023, high speed=0-1024). This value
|
||
|
* comes from the stadnard endpoint descriptor
|
||
|
* field wMaxPacketSize bits <10:0>.
|
||
|
* @param transfer_type
|
||
|
* The type of transfer this pipe is for.
|
||
|
* @param transfer_dir
|
||
|
* The direction the pipe is in. This is not
|
||
|
* used for control pipes.
|
||
|
* @param interval For ISOCHRONOUS and INTERRUPT transfers,
|
||
|
* this is how often the transfer is scheduled
|
||
|
* for. All other transfers should specify
|
||
|
* zero. The units are in frames (8000/sec at
|
||
|
* high speed, 1000/sec for full speed).
|
||
|
* @param multi_count
|
||
|
* For high speed devices, this is the maximum
|
||
|
* allowed number of packet per microframe.
|
||
|
* Specify zero for non high speed devices. This
|
||
|
* value comes from the stadnard endpoint descriptor
|
||
|
* field wMaxPacketSize bits <12:11>.
|
||
|
* @param hub_device_addr
|
||
|
* Hub device address this device is connected
|
||
|
* to. Devices connected directly to Octeon
|
||
|
* use zero. This is only used when the device
|
||
|
* is full/low speed behind a high speed hub.
|
||
|
* The address will be of the high speed hub,
|
||
|
* not and full speed hubs after it.
|
||
|
* @param hub_port Which port on the hub the device is
|
||
|
* connected. Use zero for devices connected
|
||
|
* directly to Octeon. Like hub_device_addr,
|
||
|
* this is only used for full/low speed
|
||
|
* devices behind a high speed hub.
|
||
|
*
|
||
|
* @return A non negative value is a pipe handle. Negative
|
||
|
* values are failure codes from cvmx_usb_status_t.
|
||
|
*/
|
||
|
extern int cvmx_usb_open_pipe(cvmx_usb_state_t *state,
|
||
|
cvmx_usb_pipe_flags_t flags,
|
||
|
int device_addr, int endpoint_num,
|
||
|
cvmx_usb_speed_t device_speed, int max_packet,
|
||
|
cvmx_usb_transfer_t transfer_type,
|
||
|
cvmx_usb_direction_t transfer_dir, int interval,
|
||
|
int multi_count, int hub_device_addr,
|
||
|
int hub_port);
|
||
|
|
||
|
/**
|
||
|
* Call to submit a USB Bulk transfer to a pipe.
|
||
|
*
|
||
|
* @param state USB device state populated by
|
||
|
* cvmx_usb_initialize().
|
||
|
* @param pipe_handle
|
||
|
* Handle to the pipe for the transfer.
|
||
|
* @param buffer Physical address of the data buffer in
|
||
|
* memory. Note that this is NOT A POINTER, but
|
||
|
* the full 64bit physical address of the
|
||
|
* buffer. This may be zero if buffer_length is
|
||
|
* zero.
|
||
|
* @param buffer_length
|
||
|
* Length of buffer in bytes.
|
||
|
* @param callback Function to call when this transaction
|
||
|
* completes. If the return value of this
|
||
|
* function isn't an error, then this function
|
||
|
* is guaranteed to be called when the
|
||
|
* transaction completes. If this parameter is
|
||
|
* NULL, then the generic callback registered
|
||
|
* through cvmx_usb_register_callback is
|
||
|
* called. If both are NULL, then there is no
|
||
|
* way to know when a transaction completes.
|
||
|
* @param user_data User supplied data returned when the
|
||
|
* callback is called. This is only used if
|
||
|
* callback in not NULL.
|
||
|
*
|
||
|
* @return A submitted transaction handle or negative on
|
||
|
* failure. Negative values are failure codes from
|
||
|
* cvmx_usb_status_t.
|
||
|
*/
|
||
|
extern int cvmx_usb_submit_bulk(cvmx_usb_state_t *state, int pipe_handle,
|
||
|
uint64_t buffer, int buffer_length,
|
||
|
cvmx_usb_callback_func_t callback,
|
||
|
void *user_data);
|
||
|
|
||
|
/**
|
||
|
* Call to submit a USB Interrupt transfer to a pipe.
|
||
|
*
|
||
|
* @param state USB device state populated by
|
||
|
* cvmx_usb_initialize().
|
||
|
* @param pipe_handle
|
||
|
* Handle to the pipe for the transfer.
|
||
|
* @param buffer Physical address of the data buffer in
|
||
|
* memory. Note that this is NOT A POINTER, but
|
||
|
* the full 64bit physical address of the
|
||
|
* buffer. This may be zero if buffer_length is
|
||
|
* zero.
|
||
|
* @param buffer_length
|
||
|
* Length of buffer in bytes.
|
||
|
* @param callback Function to call when this transaction
|
||
|
* completes. If the return value of this
|
||
|
* function isn't an error, then this function
|
||
|
* is guaranteed to be called when the
|
||
|
* transaction completes. If this parameter is
|
||
|
* NULL, then the generic callback registered
|
||
|
* through cvmx_usb_register_callback is
|
||
|
* called. If both are NULL, then there is no
|
||
|
* way to know when a transaction completes.
|
||
|
* @param user_data User supplied data returned when the
|
||
|
* callback is called. This is only used if
|
||
|
* callback in not NULL.
|
||
|
*
|
||
|
* @return A submitted transaction handle or negative on
|
||
|
* failure. Negative values are failure codes from
|
||
|
* cvmx_usb_status_t.
|
||
|
*/
|
||
|
extern int cvmx_usb_submit_interrupt(cvmx_usb_state_t *state, int pipe_handle,
|
||
|
uint64_t buffer, int buffer_length,
|
||
|
cvmx_usb_callback_func_t callback,
|
||
|
void *user_data);
|
||
|
|
||
|
/**
|
||
|
* Call to submit a USB Control transfer to a pipe.
|
||
|
*
|
||
|
* @param state USB device state populated by
|
||
|
* cvmx_usb_initialize().
|
||
|
* @param pipe_handle
|
||
|
* Handle to the pipe for the transfer.
|
||
|
* @param control_header
|
||
|
* USB 8 byte control header physical address.
|
||
|
* Note that this is NOT A POINTER, but the
|
||
|
* full 64bit physical address of the buffer.
|
||
|
* @param buffer Physical address of the data buffer in
|
||
|
* memory. Note that this is NOT A POINTER, but
|
||
|
* the full 64bit physical address of the
|
||
|
* buffer. This may be zero if buffer_length is
|
||
|
* zero.
|
||
|
* @param buffer_length
|
||
|
* Length of buffer in bytes.
|
||
|
* @param callback Function to call when this transaction
|
||
|
* completes. If the return value of this
|
||
|
* function isn't an error, then this function
|
||
|
* is guaranteed to be called when the
|
||
|
* transaction completes. If this parameter is
|
||
|
* NULL, then the generic callback registered
|
||
|
* through cvmx_usb_register_callback is
|
||
|
* called. If both are NULL, then there is no
|
||
|
* way to know when a transaction completes.
|
||
|
* @param user_data User supplied data returned when the
|
||
|
* callback is called. This is only used if
|
||
|
* callback in not NULL.
|
||
|
*
|
||
|
* @return A submitted transaction handle or negative on
|
||
|
* failure. Negative values are failure codes from
|
||
|
* cvmx_usb_status_t.
|
||
|
*/
|
||
|
extern int cvmx_usb_submit_control(cvmx_usb_state_t *state, int pipe_handle,
|
||
|
uint64_t control_header,
|
||
|
uint64_t buffer, int buffer_length,
|
||
|
cvmx_usb_callback_func_t callback,
|
||
|
void *user_data);
|
||
|
|
||
|
/**
|
||
|
* Flags to pass the cvmx_usb_submit_isochronous() function.
|
||
|
*/
|
||
|
typedef enum
|
||
|
{
|
||
|
CVMX_USB_ISOCHRONOUS_FLAGS_ALLOW_SHORT = 1<<0, /**< Do not return an error if a transfer is less than the maximum packet size of the device */
|
||
|
CVMX_USB_ISOCHRONOUS_FLAGS_ASAP = 1<<1, /**< Schedule the transaction as soon as possible */
|
||
|
} cvmx_usb_isochronous_flags_t;
|
||
|
|
||
|
/**
|
||
|
* Call to submit a USB Isochronous transfer to a pipe.
|
||
|
*
|
||
|
* @param state USB device state populated by
|
||
|
* cvmx_usb_initialize().
|
||
|
* @param pipe_handle
|
||
|
* Handle to the pipe for the transfer.
|
||
|
* @param start_frame
|
||
|
* Number of frames into the future to schedule
|
||
|
* this transaction.
|
||
|
* @param flags Flags to control the transfer. See
|
||
|
* cvmx_usb_isochronous_flags_t for the flag
|
||
|
* definitions.
|
||
|
* @param number_packets
|
||
|
* Number of sequential packets to transfer.
|
||
|
* "packets" is a pointer to an array of this
|
||
|
* many packet structures.
|
||
|
* @param packets Description of each transfer packet as
|
||
|
* defined by cvmx_usb_iso_packet_t. The array
|
||
|
* pointed to here must stay valid until the
|
||
|
* complete callback is called.
|
||
|
* @param buffer Physical address of the data buffer in
|
||
|
* memory. Note that this is NOT A POINTER, but
|
||
|
* the full 64bit physical address of the
|
||
|
* buffer. This may be zero if buffer_length is
|
||
|
* zero.
|
||
|
* @param buffer_length
|
||
|
* Length of buffer in bytes.
|
||
|
* @param callback Function to call when this transaction
|
||
|
* completes. If the return value of this
|
||
|
* function isn't an error, then this function
|
||
|
* is guaranteed to be called when the
|
||
|
* transaction completes. If this parameter is
|
||
|
* NULL, then the generic callback registered
|
||
|
* through cvmx_usb_register_callback is
|
||
|
* called. If both are NULL, then there is no
|
||
|
* way to know when a transaction completes.
|
||
|
* @param user_data User supplied data returned when the
|
||
|
* callback is called. This is only used if
|
||
|
* callback in not NULL.
|
||
|
*
|
||
|
* @return A submitted transaction handle or negative on
|
||
|
* failure. Negative values are failure codes from
|
||
|
* cvmx_usb_status_t.
|
||
|
*/
|
||
|
extern int cvmx_usb_submit_isochronous(cvmx_usb_state_t *state, int pipe_handle,
|
||
|
int start_frame, int flags,
|
||
|
int number_packets,
|
||
|
cvmx_usb_iso_packet_t packets[],
|
||
|
uint64_t buffer, int buffer_length,
|
||
|
cvmx_usb_callback_func_t callback,
|
||
|
void *user_data);
|
||
|
|
||
|
/**
|
||
|
* Cancel one outstanding request in a pipe. Canceling a request
|
||
|
* can fail if the transaction has already completed before cancel
|
||
|
* is called. Even after a successful cancel call, it may take
|
||
|
* a frame or two for the cvmx_usb_poll() function to call the
|
||
|
* associated callback.
|
||
|
*
|
||
|
* @param state USB device state populated by
|
||
|
* cvmx_usb_initialize().
|
||
|
* @param pipe_handle
|
||
|
* Pipe handle to cancel requests in.
|
||
|
* @param submit_handle
|
||
|
* Handle to transaction to cancel, returned by the submit function.
|
||
|
*
|
||
|
* @return CVMX_USB_SUCCESS or a negative error code defined in
|
||
|
* cvmx_usb_status_t.
|
||
|
*/
|
||
|
extern cvmx_usb_status_t cvmx_usb_cancel(cvmx_usb_state_t *state,
|
||
|
int pipe_handle, int submit_handle);
|
||
|
|
||
|
|
||
|
/**
|
||
|
* Cancel all outstanding requests in a pipe. Logically all this
|
||
|
* does is call cvmx_usb_cancel() in a loop.
|
||
|
*
|
||
|
* @param state USB device state populated by
|
||
|
* cvmx_usb_initialize().
|
||
|
* @param pipe_handle
|
||
|
* Pipe handle to cancel requests in.
|
||
|
*
|
||
|
* @return CVMX_USB_SUCCESS or a negative error code defined in
|
||
|
* cvmx_usb_status_t.
|
||
|
*/
|
||
|
extern cvmx_usb_status_t cvmx_usb_cancel_all(cvmx_usb_state_t *state,
|
||
|
int pipe_handle);
|
||
|
|
||
|
/**
|
||
|
* Close a pipe created with cvmx_usb_open_pipe().
|
||
|
*
|
||
|
* @param state USB device state populated by
|
||
|
* cvmx_usb_initialize().
|
||
|
* @param pipe_handle
|
||
|
* Pipe handle to close.
|
||
|
*
|
||
|
* @return CVMX_USB_SUCCESS or a negative error code defined in
|
||
|
* cvmx_usb_status_t. CVMX_USB_BUSY is returned if the
|
||
|
* pipe has outstanding transfers.
|
||
|
*/
|
||
|
extern cvmx_usb_status_t cvmx_usb_close_pipe(cvmx_usb_state_t *state,
|
||
|
int pipe_handle);
|
||
|
|
||
|
/**
|
||
|
* Register a function to be called when various USB events occur.
|
||
|
*
|
||
|
* @param state USB device state populated by
|
||
|
* cvmx_usb_initialize().
|
||
|
* @param reason Which event to register for.
|
||
|
* @param callback Function to call when the event occurs.
|
||
|
* @param user_data User data parameter to the function.
|
||
|
*
|
||
|
* @return CVMX_USB_SUCCESS or a negative error code defined in
|
||
|
* cvmx_usb_status_t.
|
||
|
*/
|
||
|
extern cvmx_usb_status_t cvmx_usb_register_callback(cvmx_usb_state_t *state,
|
||
|
cvmx_usb_callback_t reason,
|
||
|
cvmx_usb_callback_func_t callback,
|
||
|
void *user_data);
|
||
|
|
||
|
/**
|
||
|
* Get the current USB protocol level frame number. The frame
|
||
|
* number is always in the range of 0-0x7ff.
|
||
|
*
|
||
|
* @param state USB device state populated by
|
||
|
* cvmx_usb_initialize().
|
||
|
*
|
||
|
* @return USB frame number
|
||
|
*/
|
||
|
extern int cvmx_usb_get_frame_number(cvmx_usb_state_t *state);
|
||
|
|
||
|
/**
|
||
|
* Poll the USB block for status and call all needed callback
|
||
|
* handlers. This function is meant to be called in the interrupt
|
||
|
* handler for the USB controller. It can also be called
|
||
|
* periodically in a loop for non-interrupt based operation.
|
||
|
*
|
||
|
* @param state USB device state populated by
|
||
|
* cvmx_usb_initialize().
|
||
|
*
|
||
|
* @return CVMX_USB_SUCCESS or a negative error code defined in
|
||
|
* cvmx_usb_status_t.
|
||
|
*/
|
||
|
extern cvmx_usb_status_t cvmx_usb_poll(cvmx_usb_state_t *state);
|
||
|
|
||
|
/**
|
||
|
* Enable an endpoint for use in device mode. After this call
|
||
|
* transactions will be allowed over the endpoint. This must be
|
||
|
* called after every usb reset.
|
||
|
*
|
||
|
* @param state USB device state populated by
|
||
|
* cvmx_usb_initialize().
|
||
|
* @param endpoint_num
|
||
|
* The endpoint number to enable (0-4)
|
||
|
* @param transfer_type
|
||
|
* USB transfer type of this endpoint
|
||
|
* @param transfer_dir
|
||
|
* Direction of transfer relative to Octeon
|
||
|
* @param max_packet_size
|
||
|
* Maximum packet size support by this endpoint
|
||
|
* @param buffer Buffer to send/receive
|
||
|
* @param buffer_length
|
||
|
* Length of the buffer in bytes
|
||
|
*
|
||
|
* @return CVMX_USB_SUCCESS or a negative error code defined in
|
||
|
* cvmx_usb_status_t.
|
||
|
*/
|
||
|
extern cvmx_usb_status_t cvmx_usb_device_enable_endpoint(cvmx_usb_state_t *state,
|
||
|
int endpoint_num,
|
||
|
cvmx_usb_transfer_t transfer_type,
|
||
|
cvmx_usb_direction_t transfer_dir,
|
||
|
int max_packet_size,
|
||
|
uint64_t buffer,
|
||
|
int buffer_length);
|
||
|
|
||
|
/**
|
||
|
* Disable an endpoint in device mode.
|
||
|
*
|
||
|
* @param state USB device state populated by
|
||
|
* cvmx_usb_initialize().
|
||
|
* @param endpoint_num
|
||
|
* The endpoint number to disable (0-4)
|
||
|
*
|
||
|
* @return CVMX_USB_SUCCESS or a negative error code defined in
|
||
|
* cvmx_usb_status_t.
|
||
|
*/
|
||
|
extern cvmx_usb_status_t cvmx_usb_device_disable_endpoint(cvmx_usb_state_t *state,
|
||
|
int endpoint_num);
|
||
|
|
||
|
#ifdef __cplusplus
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
#endif /* __CVMX_USB_H__ */
|