rt-thread/bsp/phytium/libraries/standalone/drivers/usb/fxhci/fxhci_private.h

476 lines
17 KiB
C
Raw Normal View History

/*
* Copyright : (C) 2022 Phytium Information Technology, Inc.
* All Rights Reserved.
*
* This program is OPEN SOURCE software: you can redistribute it and/or modify it
* under the terms of the Phytium Public License as published by the Phytium Technology Co.,Ltd,
* either version 1.0 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the Phytium Public License for more details.
*
*
* FilePath: fxhci_private.h
* Date: 2022-02-11 13:33:12
* LastEditTime: 2022-02-18 09:16:44
* Description:  This files is for definition of XHCI internal function
*
* Modify History:
* Ver   Who        Date         Changes
* ----- ------     --------    --------------------------------------
* 1.0 zhugengyu 2022/2/7 init commit
*/
#ifndef FXHCI_PRIVATE_H
#define FXHCI_PRIVATE_H
/***************************** Include Files *********************************/
#include "fusb_private.h"
#include "fxhci_hw.h"
#include "fxhci.h"
#ifdef __cplusplus
extern "C"
{
#endif
/************************** Constant Definitions *****************************/
typedef enum
{
FXHCI_TRB_NORMAL = 1,
FXHCI_TRB_SETUP_STAGE = 2,
FXHCI_TRB_DATA_STAGE = 3,
FXHCI_TRB_STATUS_STAGE = 4,
FXHCI_TRB_LINK = 6,
FXHCI_TRB_EVENT_DATA = 7,
FXHCI_TRB_CMD_ENABLE_SLOT = 9,
FXHCI_TRB_CMD_DISABLE_SLOT = 10,
FXHCI_TRB_CMD_ADDRESS_DEV = 11,
FXHCI_TRB_CMD_CONFIGURE_EP = 12,
FXHCI_TRB_CMD_EVAL_CTX = 13,
FXHCI_TRB_CMD_RESET_EP = 14,
FXHCI_TRB_CMD_STOP_EP = 15,
FXHCI_TRB_CMD_SET_TR_DQ = 16,
FXHCI_TRB_CMD_NOOP = 23,
FXHCI_TRB_EV_TRANSFER = 32,
FXHCI_TRB_EV_CMD_CMPL = 33,
FXHCI_TRB_EV_PORTSC = 34,
FXHCI_TRB_EV_HOST = 37,
} FXhciTrbType;
enum
{
FXHCI_TRB_TRT_NO_DATA = 0,
FXHCI_TRB_TRT_OUT_DATA = 2,
FXHCI_TRB_TRT_IN_DATA = 3
};
enum
{
FXHCI_TRB_DIR_OUT = 0,
FXHCI_TRB_DIR_IN = 1
};
#define FXHCI_TRB_MAX_TD_SIZE 0x1F /* bits 21:17 of TD Size in TRB */
#define FXHCI_DMA_SIZE (64 * 1024)
#define FXHCI_TIMEOUT 1000000
enum
{
FXHCI_EP_ISOC_OUT = 1,
FXHCI_EP_BULK_OUT = 2,
FXHCI_EP_INTR_OUT = 3,
FXHCI_EP_CONTROL = 4,
FXHCI_EP_ISOC_IN = 5,
FXHCI_EP_BULK_IN = 6,
FXHCI_EP_INTR_IN = 7
};
/**************************** Type Definitions *******************************/
typedef volatile struct
{
u32 ptr_low;
u32 ptr_high;
u32 status;
u32 control;
} FXhciTrb;
typedef struct
{
FXhciTrb *ring;
FXhciTrb *cur;
FXhciTrb *last;
u8 ccs;
u8 adv;
} FXhciEvtRing;
typedef struct
{
FXhciTrb *ring;
FXhciTrb *cur;
u8 pcs;
} __attribute__((packed)) FXhciTransRing;
typedef FXhciTransRing FXhciCmdRing;
typedef volatile struct
{
u32 f1;
u32 f2;
u32 f3;
u32 f4;
u32 rsvd[4];
} FXhciSlotCtx;
typedef volatile struct
{
u32 f1;
u32 f2;
u32 tr_dq_low;
u32 tr_dq_high;
u32 f5;
u32 rsvd[3];
} FXhciEpCtx;
typedef union
{
/* set of pointers, so we can dynamically adjust Slot/EP context size */
struct
{
union
{
FXhciSlotCtx *slot;
void *raw; /* Pointer to the whole dev context. */
};
FXhciEpCtx *ep0;
FXhciEpCtx *eps1_30[FXHCI_NUM_EPS - 2];
};
FXhciEpCtx *ep[FXHCI_NUM_EPS]; /* At index 0 it's actually the slotctx,
we have it like that so we can use
the ep_id directly as index. */
} FXhciDevCtx;
typedef struct
{
union
{
/* The drop flags are located at the start of the */
u32 *drop; /* structure, so a pointer to them is equivalent */
void *raw; /* to a pointer to the whole (raw) input context. */
};
u32 *add;
FXhciDevCtx dev;
} FXhciInputCtx;
typedef struct
{
u32 seg_base_lo;
u32 seg_base_hi;
u32 seg_size;
u32 rsvd;
} FXhciErstEntry;
typedef struct
{
size_t size; /* Size of each transfer */
size_t count; /* The number of TRBs to fill at once */
FXhciTrb *next; /* The next TRB expected to be processed by the controller */
FXhciTrb *ready; /* The last TRB in the transfer ring processed by the controller */
FUsbEndpoint *ep;
} FXhciIntrQ;
typedef struct
{
FXhciDevCtx ctx;
FXhciTransRing *transfer_rings[FXHCI_NUM_EPS];
FXhciIntrQ *interrupt_queues[FXHCI_NUM_EPS];
} FXhciDevInfo;
typedef enum
{
FXHCI_DMA_SET_ADDR = 0,
FXHCI_DMA_INPUT_CTX,
FXHCI_DMA_TRANS_RING,
FXHCI_DMA_TRANS_RING_TRB,
FXHCI_MAX_DMA_TYPE
} FXhciDMAType;
typedef struct
{
FXhciDMAType type;
#define FXHCI_MAX_DMA_ENTRY 10
void *entries[FXHCI_MAX_DMA_ENTRY];
uintptr count;
} FXhciDMABuffer;
typedef struct
{
/* R/W, volatile, Memory -> bitfields allowed */
u64 *dcbaa; /* pointers to sp_ptrs and output (device) contexts */
u64 *sp_ptrs; /* pointers to scratchpad buffers */
FXhciCmdRing cr;
FXhciEvtRing er;
volatile FXhciErstEntry *ev_ring_table;
FUsbDev *roothub;
u8 max_slots_en;
FXhciDevInfo *dev; /* array of devinfos by slot_id */
FUsb *usb;
FXhciMMIO mmio;
} FXhci;
/************************** Variable Definitions *****************************/
/***************** Macros (Inline Functions) Definitions *********************/
#define FXHCI_MASK(startbit, lenbit) (((1<<(lenbit))-1)<<(startbit))
/* shorcut to access TRB */
#define FXHCI_TRB_PORT_FIELD ptr_low /* Pointer field of Port TRB */
#define FXHCI_TRB_PORT_START 24
#define FXHCI_TRB_PORT_LEN 8
#define FXHCI_TRB_TL_FIELD status /* TL - Transfer Length */
#define FXHCI_TRB_TL_START 0
#define FXHCI_TRB_TL_LEN 17
#define FXHCI_TRB_EVTL_FIELD status /* EVTL - (Event TRB) Transfer Length */
#define FXHCI_TRB_EVTL_START 0
#define FXHCI_TRB_EVTL_LEN 24
#define FXHCI_TRB_TDS_FIELD status /* TDS - TD Size */
#define FXHCI_TRB_TDS_START 17
#define FXHCI_TRB_TDS_LEN 5
#define FXHCI_TRB_CC_FIELD status /* CC - Completion Code */
#define FXHCI_TRB_CC_START 24
#define FXHCI_TRB_CC_LEN 8
#define FXHCI_TRB_C_FIELD control /* C - Cycle Bit */
#define FXHCI_TRB_C_START 0
#define FXHCI_TRB_C_LEN 1
#define FXHCI_TRB_TC_FIELD control /* TC - Toggle Cycle */
#define FXHCI_TRB_TC_START 1
#define FXHCI_TRB_TC_LEN 1
#define FXHCI_TRB_ENT_FIELD control /* ENT - Evaluate Next TRB */
#define FXHCI_TRB_ENT_START 1
#define FXHCI_TRB_ENT_LEN 1
#define FXHCI_TRB_ISP_FIELD control /* ISP - Interrupt-on Short Packet */
#define FXHCI_TRB_ISP_START 2
#define FXHCI_TRB_ISP_LEN 1
#define FXHCI_TRB_CH_FIELD control /* CH - Chain Bit */
#define FXHCI_TRB_CH_START 4
#define FXHCI_TRB_CH_LEN 1
#define FXHCI_TRB_IOC_FIELD control /* IOC - Interrupt On Completion */
#define FXHCI_TRB_IOC_START 5
#define FXHCI_TRB_IOC_LEN 1
#define FXHCI_TRB_IDT_FIELD control /* IDT - Immediate Data */
#define FXHCI_TRB_IDT_START 6
#define FXHCI_TRB_IDT_LEN 1
#define FXHCI_TRB_DC_FIELD control /* DC - Deconfigure */
#define FXHCI_TRB_DC_START 9
#define FXHCI_TRB_DC_LEN 1
#define FXHCI_TRB_TT_FIELD control /* TT - TRB Type */
#define FXHCI_TRB_TT_START 10
#define FXHCI_TRB_TT_LEN 6
#define FXHCI_TRB_TRT_FIELD control /* TRT - Transfer Type */
#define FXHCI_TRB_TRT_START 16
#define FXHCI_TRB_TRT_LEN 2
#define FXHCI_TRB_DIR_FIELD control /* DIR - Direction */
#define FXHCI_TRB_DIR_START 16
#define FXHCI_TRB_DIR_LEN 1
#define FXHCI_TRB_EP_FIELD control /* EP - Endpoint ID */
#define FXHCI_TRB_EP_START 16
#define FXHCI_TRB_EP_LEN 5
#define FXHCI_TRB_ID_FIELD control /* ID - Slot ID */
#define FXHCI_TRB_ID_START 24
#define FXHCI_TRB_ID_LEN 8
#define FXHCI_TRB_MASK(tok) FXHCI_MASK(FXHCI_TRB_##tok##_START, FXHCI_TRB_##tok##_LEN)
#define FXHCI_TRB_GET(tok, trb) (((trb)->FXHCI_TRB_##tok##_FIELD & FXHCI_TRB_MASK(tok)) \
>> FXHCI_TRB_##tok##_START)
#define FXHCI_TRB_SET(tok, trb, to) (trb)->FXHCI_TRB_##tok##_FIELD = \
(((trb)->FXHCI_TRB_##tok##_FIELD & ~FXHCI_TRB_MASK(tok)) | \
(((to) << FXHCI_TRB_##tok##_START) & FXHCI_TRB_MASK(tok)))
#define FXHCI_TRB_DUMP(dumper, tok, trb) dumper(" "#tok"\t0x%04x ", FXHCI_TRB_GET(tok, trb))
#define FXHCI_TRB_CYCLE (1 << 0)
/* shortcut to access slot context */
#define FXHCI_SC_ROUTE_FIELD f1 /* ROUTE - Route String */
#define FXHCI_SC_ROUTE_START 0
#define FXHCI_SC_ROUTE_LEN 20
#define FXHCI_SC_SPEED1_FIELD f1 /* SPEED - Port speed plus one (compared to FUsbSpeed enum) */
#define FXHCI_SC_SPEED1_START 20
#define FXHCI_SC_SPEED1_LEN 4
#define FXHCI_SC_MTT_FIELD f1 /* MTT - Multi Transaction Translator */
#define FXHCI_SC_MTT_START 25
#define FXHCI_SC_MTT_LEN 1
#define FXHCI_SC_HUB_FIELD f1 /* HUB - Is this a hub? */
#define FXHCI_SC_HUB_START 26
#define FXHCI_SC_HUB_LEN 1
#define FXHCI_SC_CTXENT_FIELD f1 /* CTXENT - Context Entries (number of following ep contexts) */
#define FXHCI_SC_CTXENT_START 27
#define FXHCI_SC_CTXENT_LEN 5
#define FXHCI_SC_RHPORT_FIELD f2 /* RHPORT - Root Hub Port Number */
#define FXHCI_SC_RHPORT_START 16
#define FXHCI_SC_RHPORT_LEN 8
#define FXHCI_SC_NPORTS_FIELD f2 /* NPORTS - Number of Ports */
#define FXHCI_SC_NPORTS_START 24
#define FXHCI_SC_NPORTS_LEN 8
#define FXHCI_SC_TTID_FIELD f3 /* TTID - TT Hub Slot ID */
#define FXHCI_SC_TTID_START 0
#define FXHCI_SC_TTID_LEN 8
#define FXHCI_SC_TTPORT_FIELD f3 /* TTPORT - TT Port Number */
#define FXHCI_SC_TTPORT_START 8
#define FXHCI_SC_TTPORT_LEN 8
#define FXHCI_SC_TTT_FIELD f3 /* TTT - TT Think Time */
#define FXHCI_SC_TTT_START 16
#define FXHCI_SC_TTT_LEN 2
#define FXHCI_SC_UADDR_FIELD f4 /* UADDR - USB Device Address */
#define FXHCI_SC_UADDR_START 0
#define FXHCI_SC_UADDR_LEN 8
#define FXHCI_SC_STATE_FIELD f4 /* STATE - Slot State */
#define FXHCI_SC_STATE_START 27
#define FXHCI_SC_STATE_LEN 5
#define FXHCI_SC_MASK(tok) FXHCI_MASK(FXHCI_SC_##tok##_START, FXHCI_SC_##tok##_LEN)
#define FXHCI_SC_GET(tok, sc) (((sc)->FXHCI_SC_##tok##_FIELD & FXHCI_SC_MASK(tok)) \
>> FXHCI_SC_##tok##_START)
#define FXHCI_SC_SET(tok, sc, to) (sc)->FXHCI_SC_##tok##_FIELD = \
(((sc)->FXHCI_SC_##tok##_FIELD & ~FXHCI_SC_MASK(tok)) | \
(((to) << FXHCI_SC_##tok##_START) & FXHCI_SC_MASK(tok)))
#define FXHCI_SC_DUMP(dumper, tok, sc) dumper(" "#tok"\t0x%04x ", FXHCI_SC_GET(tok, sc))
/* shortcut to access endpoint context */
#define FXHCI_EC_STATE_FIELD f1 /* STATE - Endpoint State */
#define FXHCI_EC_STATE_START 0
#define FXHCI_EC_STATE_LEN 3
#define FXHCI_EC_INTVAL_FIELD f1 /* INTVAL - Interval */
#define FXHCI_EC_INTVAL_START 16
#define FXHCI_EC_INTVAL_LEN 8
#define FXHCI_EC_CERR_FIELD f2 /* CERR - Error Count */
#define FXHCI_EC_CERR_START 1
#define FXHCI_EC_CERR_LEN 2
#define FXHCI_EC_TYPE_FIELD f2 /* TYPE - EP Type */
#define FXHCI_EC_TYPE_START 3
#define FXHCI_EC_TYPE_LEN 3
#define FXHCI_EC_MBS_FIELD f2 /* MBS - Max Burst Size */
#define FXHCI_EC_MBS_START 8
#define FXHCI_EC_MBS_LEN 8
#define FXHCI_EC_MPS_FIELD f2 /* MPS - Max Packet Size */
#define FXHCI_EC_MPS_START 16
#define FXHCI_EC_MPS_LEN 16
#define FXHCI_EC_DCS_FIELD tr_dq_low /* DCS - Dequeue Cycle State */
#define FXHCI_EC_DCS_START 0
#define FXHCI_EC_DCS_LEN 1
#define FXHCI_EC_AVRTRB_FIELD f5 /* AVRTRB - Average TRB Length */
#define FXHCI_EC_AVRTRB_START 0
#define FXHCI_EC_AVRTRB_LEN 16
#define FXHCI_EC_MXESIT_FIELD f5 /* MXESIT - Max ESIT Payload */
#define FXHCI_EC_MXESIT_START 16
#define FXHCI_EC_MXESIT_LEN 16
#define FXHCI_EC_BPKTS_FIELD rsvd[0] /* BPKTS - packets tx in scheduled uframe */
#define FXHCI_EC_BPKTS_START 0
#define FXHCI_EC_BPKTS_LEN 6
#define FXHCI_EC_BBM_FIELD rsvd[0] /* BBM - burst mode for scheduling */
#define FXHCI_EC_BBM_START 11
#define FXHCI_EC_BBM_LEN 1
#define FXHCI_EC_MASK(tok) FXHCI_MASK(FXHCI_EC_##tok##_START, FXHCI_EC_##tok##_LEN)
#define FXHCI_EC_GET(tok, ec) (((ec)->FXHCI_EC_##tok##_FIELD & FXHCI_EC_MASK(tok)) \
>> FXHCI_EC_##tok##_START)
#define FXHCI_EC_SET(tok, ec, to) (ec)->FXHCI_EC_##tok##_FIELD = \
(((ec)->FXHCI_EC_##tok##_FIELD & ~FXHCI_EC_MASK(tok)) | \
(((to) << FXHCI_EC_##tok##_START) & FXHCI_EC_MASK(tok)))
#define FXHCI_EC_DUMP(dumper, tok, ec) dumper(" "#tok"\t0x%04x ", FXHCI_EC_GET(tok, ec))
/* the current operational state of the endpoint. */
enum
{
FXHCI_EC_STATE_DISABLED = 0, /* endpoint is not operational */
FXHCI_EC_STATE_RUNNING = 1, /* endpoint is operational */
FXHCI_EC_STATE_HALTED = 2, /* endpoint is halted due to a Halt condition detected on the USB */
FXHCI_EC_STATE_STOPPED = 3, /* endpoint is not running due to a Stop Endpoint Command */
FXHCI_EC_STATE_ERROR = 4 /* endpoint is not running due to a TRB Error */
};
#define FXHCI_INST_GET(controller) ((FXhci*)((controller)->instance))
static inline int FXhciEpId(const FUsbEndpoint *const ep)
{
/* calculate endpoint ID (Device Context Index (DCI)) The range of DCI values is 0 to 31.
* For Isoch, Interrupt, or Bulk type endpoints
* DCI = (Endpoint Number * 2) + Direction , Direction = 0 for OUT 1 for IN
* For Control type endpoints
* DCI = (Endpoint Number * 2) + 1.
*/
return ((ep->endpoint & 0x7f) * 2) + (ep->direction != FUSB_OUT);
}
#define FXHCI_EP0_ID 1
/************************** Function Prototypes ******************************/
/* 初始化Roothub */
void FXhciRootHubInit(FUsbDev *dev);
/* 分配一段对齐的内存 */
void *FXhciAlign(FXhci *xhci, const size_t min_align, const size_t size);
/* 初始化TRB ring */
void FXhciInitCycleRing(FXhciTransRing *ring, const size_t ring_size);
/* 设备USB设备的地址 */
FUsbDev *FXhciSetAddress(FUsbHc *hc, FUsbSpeed speed, int hubport, int hubaddr);
/* 完成USB设备配置 */
FXhciTransCode FXhciFinishDevConfig(FUsbDev *hc);
/* 删除指定USB设备实例 */
void FXhciDestoryDev(FUsbHc *xhci, int slot_id);
/* 重置Event TRB ring */
void FXhciResetEvtRing(FXhciEvtRing *ring);
void FXhciAdvanceEvtRing(FXhci *xhci);
void FXhciUpdateEvtDQ(FXhci *xhci);
void FXhciHandleEvts(FXhci *xhci);
FXhciTransCode FXhciWaitForCmdAborted(FXhci *xhci, const FXhciTrb *trb);
FXhciTransCode FXhciWaitForCmdDone(FXhci *xhci, const FXhciTrb *trb, int clear_event);
FXhciTransCode FXhciWaitForTransfer(FXhci *xhci, const int slot_id, const int ep_id);
void FXhciClearTrb(FXhciTrb *trb, int pcs);
FXhciTrb *FXhciNextCmdTrb(FXhci *xhci);
void FXhciPostCmd(FXhci *xhci);
FXhciTransCode FXhciCmdNop(FXhci *const xhci);
FXhciTransCode FXhciCmdEnableSlot(FXhci *xhci, int *slot_id);
FXhciTransCode FXhciCmdDisableSlot(FXhci *xhci, int slot_id);
FXhciTransCode FXhciCmdAddressDevice(FXhci *xhci, int slot_id, FXhciInputCtx *ctx);
FXhciTransCode FXhciCmdConfigureEp(FXhci *xhci, int slot_id, int config_id, FXhciInputCtx *ctx);
FXhciTransCode FXhciCmdEvaluateCtx(FXhci *xhci, int slot_id, FXhciInputCtx *ctx);
FXhciTransCode FXhciCmdResetEp(FXhci *xhci, int slot_id, int ep);
FXhciTransCode FXhciCmdStopEp(FXhci *xhci, int slot_id, int ep);
FXhciTransCode FXhciCmdSetTrDq(FXhci *xhci, int slot_id, int ep, FXhciTrb *trb, int dcs);
void FXhciDumpSlotCtx(const FXhciSlotCtx *ctx);
void FXhciDumpEpCtx(const FXhciEpCtx *ctx);
void FXhciDumpDevCtx(const FXhciDevCtx *ctx, const u32 ctx_mask);
void FXhciDumpInputCtx(const FXhciInputCtx *ctx);
void FXhciDumpTransferTrb(const FXhciTrb *trb);
void FXhciDumpTransferTrbs(const FXhciTrb *first, const FXhciTrb *last);
/* 支持带TAG的内存分配用于跟踪动态内存使用 */
#ifdef FMEMP_TAG_DEBUG
void *FXhciAlignTag(FXhci *const xhci, const size_t min_align, const size_t size, const char *file, unsigned long line, const char *msg);
#define FXHCI_ALIGN(xhci, min_align, size) FXhciAlignTag((xhci), (min_align), (size), __FILE__, __LINE__, "")
#else
#define FXHCI_ALIGN(xhci, min_align, size) FXhciAlign((xhci), (min_align), (size))
#endif
#ifdef __cplusplus
}
#endif
#endif