diff options
Diffstat (limited to 'drivers/usb/host/dwc_otg/dwc_otg_cfi.h')
-rw-r--r-- | drivers/usb/host/dwc_otg/dwc_otg_cfi.h | 320 |
1 files changed, 320 insertions, 0 deletions
diff --git a/drivers/usb/host/dwc_otg/dwc_otg_cfi.h b/drivers/usb/host/dwc_otg/dwc_otg_cfi.h new file mode 100644 index 000000000000..55fd337a283c --- /dev/null +++ b/drivers/usb/host/dwc_otg/dwc_otg_cfi.h @@ -0,0 +1,320 @@ +/* ========================================================================== + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter, + * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless + * otherwise expressly agreed to in writing between Synopsys and you. + * + * The Software IS NOT an item of Licensed Software or Licensed Product under + * any End User Software License Agreement or Agreement for Licensed Product + * with Synopsys or any supplement thereto. You are permitted to use and + * redistribute this Software in source and binary forms, with or without + * modification, provided that redistributions of source code must retain this + * notice. You may not view, use, disclose, copy or distribute this file or + * any information contained herein except pursuant to this license grant from + * Synopsys. If you do not agree with this notice, including the disclaimer + * below, then you are not authorized to use the Software. + * + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * ========================================================================== */ + +#if !defined(__DWC_OTG_CFI_H__) +#define __DWC_OTG_CFI_H__ + +#include "dwc_otg_pcd.h" +#include "dwc_cfi_common.h" + +/** + * @file + * This file contains the CFI related OTG PCD specific common constants, + * interfaces(functions and macros) and data structures.The CFI Protocol is an + * optional interface for internal testing purposes that a DUT may implement to + * support testing of configurable features. + * + */ + +struct dwc_otg_pcd; +struct dwc_otg_pcd_ep; + +/** OTG CFI Features (properties) ID constants */ +/** This is a request for all Core Features */ +#define FT_ID_DMA_MODE 0x0001 +#define FT_ID_DMA_BUFFER_SETUP 0x0002 +#define FT_ID_DMA_BUFF_ALIGN 0x0003 +#define FT_ID_DMA_CONCAT_SETUP 0x0004 +#define FT_ID_DMA_CIRCULAR 0x0005 +#define FT_ID_THRESHOLD_SETUP 0x0006 +#define FT_ID_DFIFO_DEPTH 0x0007 +#define FT_ID_TX_FIFO_DEPTH 0x0008 +#define FT_ID_RX_FIFO_DEPTH 0x0009 + +/**********************************************************/ +#define CFI_INFO_DEF + +#ifdef CFI_INFO_DEF +#define CFI_INFO(fmt...) DWC_PRINTF("CFI: " fmt); +#else +#define CFI_INFO(fmt...) +#endif + +#define min(x,y) ({ \ + x < y ? x : y; }) + +#define max(x,y) ({ \ + x > y ? x : y; }) + +/** + * Descriptor DMA SG Buffer setup structure (SG buffer). This structure is + * also used for setting up a buffer for Circular DDMA. + */ +struct _ddma_sg_buffer_setup { +#define BS_SG_VAL_DESC_LEN 6 + /* The OUT EP address */ + uint8_t bOutEndpointAddress; + /* The IN EP address */ + uint8_t bInEndpointAddress; + /* Number of bytes to put between transfer segments (must be DWORD boundaries) */ + uint8_t bOffset; + /* The number of transfer segments (a DMA descriptors per each segment) */ + uint8_t bCount; + /* Size (in byte) of each transfer segment */ + uint16_t wSize; +} __attribute__ ((packed)); +typedef struct _ddma_sg_buffer_setup ddma_sg_buffer_setup_t; + +/** Descriptor DMA Concatenation Buffer setup structure */ +struct _ddma_concat_buffer_setup_hdr { +#define BS_CONCAT_VAL_HDR_LEN 4 + /* The endpoint for which the buffer is to be set up */ + uint8_t bEndpointAddress; + /* The count of descriptors to be used */ + uint8_t bDescCount; + /* The total size of the transfer */ + uint16_t wSize; +} __attribute__ ((packed)); +typedef struct _ddma_concat_buffer_setup_hdr ddma_concat_buffer_setup_hdr_t; + +/** Descriptor DMA Concatenation Buffer setup structure */ +struct _ddma_concat_buffer_setup { + /* The SG header */ + ddma_concat_buffer_setup_hdr_t hdr; + + /* The XFER sizes pointer (allocated dynamically) */ + uint16_t *wTxBytes; +} __attribute__ ((packed)); +typedef struct _ddma_concat_buffer_setup ddma_concat_buffer_setup_t; + +/** Descriptor DMA Alignment Buffer setup structure */ +struct _ddma_align_buffer_setup { +#define BS_ALIGN_VAL_HDR_LEN 2 + uint8_t bEndpointAddress; + uint8_t bAlign; +} __attribute__ ((packed)); +typedef struct _ddma_align_buffer_setup ddma_align_buffer_setup_t; + +/** Transmit FIFO Size setup structure */ +struct _tx_fifo_size_setup { + uint8_t bEndpointAddress; + uint16_t wDepth; +} __attribute__ ((packed)); +typedef struct _tx_fifo_size_setup tx_fifo_size_setup_t; + +/** Transmit FIFO Size setup structure */ +struct _rx_fifo_size_setup { + uint16_t wDepth; +} __attribute__ ((packed)); +typedef struct _rx_fifo_size_setup rx_fifo_size_setup_t; + +/** + * struct cfi_usb_ctrlrequest - the CFI implementation of the struct usb_ctrlrequest + * This structure encapsulates the standard usb_ctrlrequest and adds a pointer + * to the data returned in the data stage of a 3-stage Control Write requests. + */ +struct cfi_usb_ctrlrequest { + uint8_t bRequestType; + uint8_t bRequest; + uint16_t wValue; + uint16_t wIndex; + uint16_t wLength; + uint8_t *data; +} UPACKED; + +/*---------------------------------------------------------------------------*/ + +/** + * The CFI wrapper of the enabled and activated dwc_otg_pcd_ep structures. + * This structure is used to store the buffer setup data for any + * enabled endpoint in the PCD. + */ +struct cfi_ep { + /* Entry for the list container */ + dwc_list_link_t lh; + /* Pointer to the active PCD endpoint structure */ + struct dwc_otg_pcd_ep *ep; + /* The last descriptor in the chain of DMA descriptors of the endpoint */ + struct dwc_otg_dma_desc *dma_desc_last; + /* The SG feature value */ + ddma_sg_buffer_setup_t *bm_sg; + /* The Circular feature value */ + ddma_sg_buffer_setup_t *bm_circ; + /* The Concatenation feature value */ + ddma_concat_buffer_setup_t *bm_concat; + /* The Alignment feature value */ + ddma_align_buffer_setup_t *bm_align; + /* XFER length */ + uint32_t xfer_len; + /* + * Count of DMA descriptors currently used. + * The total should not exceed the MAX_DMA_DESCS_PER_EP value + * defined in the dwc_otg_cil.h + */ + uint32_t desc_count; +}; +typedef struct cfi_ep cfi_ep_t; + +typedef struct cfi_dma_buff { +#define CFI_IN_BUF_LEN 1024 +#define CFI_OUT_BUF_LEN 1024 + dma_addr_t addr; + uint8_t *buf; +} cfi_dma_buff_t; + +struct cfiobject; + +/** + * This is the interface for the CFI operations. + * + * @param ep_enable Called when any endpoint is enabled and activated. + * @param release Called when the CFI object is released and it needs to correctly + * deallocate the dynamic memory + * @param ctrl_write_complete Called when the data stage of the request is complete + */ +typedef struct cfi_ops { + int (*ep_enable) (struct cfiobject * cfi, struct dwc_otg_pcd * pcd, + struct dwc_otg_pcd_ep * ep); + void *(*ep_alloc_buf) (struct cfiobject * cfi, struct dwc_otg_pcd * pcd, + struct dwc_otg_pcd_ep * ep, dma_addr_t * dma, + unsigned size, gfp_t flags); + void (*release) (struct cfiobject * cfi); + int (*ctrl_write_complete) (struct cfiobject * cfi, + struct dwc_otg_pcd * pcd); + void (*build_descriptors) (struct cfiobject * cfi, + struct dwc_otg_pcd * pcd, + struct dwc_otg_pcd_ep * ep, + dwc_otg_pcd_request_t * req); +} cfi_ops_t; + +struct cfiobject { + cfi_ops_t ops; + struct dwc_otg_pcd *pcd; + struct usb_gadget *gadget; + + /* Buffers used to send/receive CFI-related request data */ + cfi_dma_buff_t buf_in; + cfi_dma_buff_t buf_out; + + /* CFI specific Control request wrapper */ + struct cfi_usb_ctrlrequest ctrl_req; + + /* The list of active EP's in the PCD of type cfi_ep_t */ + dwc_list_link_t active_eps; + + /* This flag shall control the propagation of a specific request + * to the gadget's processing routines. + * 0 - no gadget handling + * 1 - the gadget needs to know about this request (w/o completing a status + * phase - just return a 0 to the _setup callback) + */ + uint8_t need_gadget_att; + + /* Flag indicating whether the status IN phase needs to be + * completed by the PCD + */ + uint8_t need_status_in_complete; +}; +typedef struct cfiobject cfiobject_t; + +#define DUMP_MSG + +#if defined(DUMP_MSG) +static inline void dump_msg(const u8 * buf, unsigned int length) +{ + unsigned int start, num, i; + char line[52], *p; + + if (length >= 512) + return; + + start = 0; + while (length > 0) { + num = min(length, 16u); + p = line; + for (i = 0; i < num; ++i) { + if (i == 8) + *p++ = ' '; + DWC_SPRINTF(p, " %02x", buf[i]); + p += 3; + } + *p = 0; + DWC_DEBUG("%6x: %s\n", start, line); + buf += num; + start += num; + length -= num; + } +} +#else +static inline void dump_msg(const u8 * buf, unsigned int length) +{ +} +#endif + +/** + * This function returns a pointer to cfi_ep_t object with the addr address. + */ +static inline struct cfi_ep *get_cfi_ep_by_addr(struct cfiobject *cfi, + uint8_t addr) +{ + struct cfi_ep *pcfiep; + dwc_list_link_t *tmp; + + DWC_LIST_FOREACH(tmp, &cfi->active_eps) { + pcfiep = DWC_LIST_ENTRY(tmp, struct cfi_ep, lh); + + if (pcfiep->ep->desc->bEndpointAddress == addr) { + return pcfiep; + } + } + + return NULL; +} + +/** + * This function returns a pointer to cfi_ep_t object that matches + * the dwc_otg_pcd_ep object. + */ +static inline struct cfi_ep *get_cfi_ep_by_pcd_ep(struct cfiobject *cfi, + struct dwc_otg_pcd_ep *ep) +{ + struct cfi_ep *pcfiep = NULL; + dwc_list_link_t *tmp; + + DWC_LIST_FOREACH(tmp, &cfi->active_eps) { + pcfiep = DWC_LIST_ENTRY(tmp, struct cfi_ep, lh); + if (pcfiep->ep == ep) { + return pcfiep; + } + } + return NULL; +} + +int cfi_setup(struct dwc_otg_pcd *pcd, struct cfi_usb_ctrlrequest *ctrl); + +#endif /* (__DWC_OTG_CFI_H__) */ |