mirror of
https://github.com/Qortal/Brooklyn.git
synced 2025-01-31 15:22:18 +00:00
321 lines
9.7 KiB
C
321 lines
9.7 KiB
C
/* ==========================================================================
|
|
* 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__) */
|