mirror of https://github.com/Qortal/Brooklyn
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
489 lines
12 KiB
489 lines
12 KiB
/* SPDX-License-Identifier: GPL-2.0+ */ |
|
/* |
|
* bdc.h - header for the BRCM BDC USB3.0 device controller |
|
* |
|
* Copyright (C) 2014 Broadcom Corporation |
|
* |
|
* Author: Ashwini Pahuja |
|
*/ |
|
|
|
#ifndef __LINUX_BDC_H__ |
|
#define __LINUX_BDC_H__ |
|
|
|
#include <linux/kernel.h> |
|
#include <linux/usb.h> |
|
#include <linux/device.h> |
|
#include <linux/spinlock.h> |
|
#include <linux/list.h> |
|
#include <linux/dma-mapping.h> |
|
#include <linux/mm.h> |
|
#include <linux/debugfs.h> |
|
#include <linux/usb/ch9.h> |
|
#include <linux/usb/gadget.h> |
|
#include <asm/unaligned.h> |
|
|
|
#define BRCM_BDC_NAME "bdc" |
|
#define BRCM_BDC_DESC "Broadcom USB Device Controller driver" |
|
|
|
#define DMA_ADDR_INVALID (~(dma_addr_t)0) |
|
|
|
/* BDC command operation timeout in usec*/ |
|
#define BDC_CMD_TIMEOUT 1000 |
|
/* BDC controller operation timeout in usec*/ |
|
#define BDC_COP_TIMEOUT 500 |
|
|
|
/* |
|
* Maximum size of ep0 response buffer for ch9 requests, |
|
* the set_sel request uses 6 so far, the max. |
|
*/ |
|
#define EP0_RESPONSE_BUFF 6 |
|
/* Start with SS as default */ |
|
#define EP0_MAX_PKT_SIZE 512 |
|
|
|
/* 64 entries in a SRR */ |
|
#define NUM_SR_ENTRIES 64 |
|
|
|
/* Num of bds per table */ |
|
#define NUM_BDS_PER_TABLE 64 |
|
|
|
/* Num of tables in bd list for control,bulk and Int ep */ |
|
#define NUM_TABLES 2 |
|
|
|
/* Num of tables in bd list for Isoch ep */ |
|
#define NUM_TABLES_ISOCH 6 |
|
|
|
/* U1 Timeout default: 248usec */ |
|
#define U1_TIMEOUT 0xf8 |
|
|
|
/* Interrupt coalescence in usec */ |
|
#define INT_CLS 500 |
|
|
|
/* Register offsets */ |
|
/* Configuration and Capability registers */ |
|
#define BDC_BDCCFG0 0x00 |
|
#define BDC_BDCCFG1 0x04 |
|
#define BDC_BDCCAP0 0x08 |
|
#define BDC_BDCCAP1 0x0c |
|
#define BDC_CMDPAR0 0x10 |
|
#define BDC_CMDPAR1 0x14 |
|
#define BDC_CMDPAR2 0x18 |
|
#define BDC_CMDSC 0x1c |
|
#define BDC_USPC 0x20 |
|
#define BDC_USPPMS 0x28 |
|
#define BDC_USPPM2 0x2c |
|
#define BDC_SPBBAL 0x38 |
|
#define BDC_SPBBAH 0x3c |
|
#define BDC_BDCSC 0x40 |
|
#define BDC_XSFNTF 0x4c |
|
|
|
#define BDC_DVCSA 0x50 |
|
#define BDC_DVCSB 0x54 |
|
#define BDC_EPSTS0 0x60 |
|
#define BDC_EPSTS1 0x64 |
|
#define BDC_EPSTS2 0x68 |
|
#define BDC_EPSTS3 0x6c |
|
#define BDC_EPSTS4 0x70 |
|
#define BDC_EPSTS5 0x74 |
|
#define BDC_EPSTS6 0x78 |
|
#define BDC_EPSTS7 0x7c |
|
#define BDC_SRRBAL(n) (0x200 + ((n) * 0x10)) |
|
#define BDC_SRRBAH(n) (0x204 + ((n) * 0x10)) |
|
#define BDC_SRRINT(n) (0x208 + ((n) * 0x10)) |
|
#define BDC_INTCTLS(n) (0x20c + ((n) * 0x10)) |
|
|
|
/* Extended capability regs */ |
|
#define BDC_FSCNOC 0xcd4 |
|
#define BDC_FSCNIC 0xce4 |
|
#define NUM_NCS(p) ((p) >> 28) |
|
|
|
/* Register bit fields and Masks */ |
|
/* BDC Configuration 0 */ |
|
#define BDC_PGS(p) (((p) & (0x7 << 8)) >> 8) |
|
#define BDC_SPB(p) ((p) & 0x7) |
|
|
|
/* BDC Capability1 */ |
|
#define BDC_P64 BIT(0) |
|
|
|
/* BDC Command register */ |
|
#define BDC_CMD_FH 0xe |
|
#define BDC_CMD_DNC 0x6 |
|
#define BDC_CMD_EPO 0x4 |
|
#define BDC_CMD_BLA 0x3 |
|
#define BDC_CMD_EPC 0x2 |
|
#define BDC_CMD_DVC 0x1 |
|
#define BDC_CMD_CWS BIT(5) |
|
#define BDC_CMD_CST(p) (((p) & (0xf << 6))>>6) |
|
#define BDC_CMD_EPN(p) (((p) & 0x1f) << 10) |
|
#define BDC_SUB_CMD_ADD (0x1 << 17) |
|
#define BDC_SUB_CMD_FWK (0x4 << 17) |
|
/* Reset sequence number */ |
|
#define BDC_CMD_EPO_RST_SN (0x1 << 16) |
|
#define BDC_CMD_EP0_XSD (0x1 << 16) |
|
#define BDC_SUB_CMD_ADD_EP (0x1 << 17) |
|
#define BDC_SUB_CMD_DRP_EP (0x2 << 17) |
|
#define BDC_SUB_CMD_EP_STP (0x2 << 17) |
|
#define BDC_SUB_CMD_EP_STL (0x4 << 17) |
|
#define BDC_SUB_CMD_EP_RST (0x1 << 17) |
|
#define BDC_CMD_SRD BIT(27) |
|
|
|
/* CMD completion status */ |
|
#define BDC_CMDS_SUCC 0x1 |
|
#define BDC_CMDS_PARA 0x3 |
|
#define BDC_CMDS_STAT 0x4 |
|
#define BDC_CMDS_FAIL 0x5 |
|
#define BDC_CMDS_INTL 0x6 |
|
#define BDC_CMDS_BUSY 0xf |
|
|
|
/* CMDSC Param 2 shifts */ |
|
#define EPT_SHIFT 22 |
|
#define MP_SHIFT 10 |
|
#define MB_SHIFT 6 |
|
#define EPM_SHIFT 4 |
|
|
|
/* BDC USPSC */ |
|
#define BDC_VBC BIT(31) |
|
#define BDC_PRC BIT(30) |
|
#define BDC_PCE BIT(29) |
|
#define BDC_CFC BIT(28) |
|
#define BDC_PCC BIT(27) |
|
#define BDC_PSC BIT(26) |
|
#define BDC_VBS BIT(25) |
|
#define BDC_PRS BIT(24) |
|
#define BDC_PCS BIT(23) |
|
#define BDC_PSP(p) (((p) & (0x7 << 20))>>20) |
|
#define BDC_SCN BIT(8) |
|
#define BDC_SDC BIT(7) |
|
#define BDC_SWS BIT(4) |
|
|
|
#define BDC_USPSC_RW (BDC_SCN|BDC_SDC|BDC_SWS|0xf) |
|
#define BDC_PSP(p) (((p) & (0x7 << 20))>>20) |
|
|
|
#define BDC_SPEED_FS 0x1 |
|
#define BDC_SPEED_LS 0x2 |
|
#define BDC_SPEED_HS 0x3 |
|
#define BDC_SPEED_SS 0x4 |
|
|
|
#define BDC_PST(p) ((p) & 0xf) |
|
#define BDC_PST_MASK 0xf |
|
|
|
/* USPPMS */ |
|
#define BDC_U2E BIT(31) |
|
#define BDC_U1E BIT(30) |
|
#define BDC_U2A BIT(29) |
|
#define BDC_PORT_W1S BIT(17) |
|
#define BDC_U1T(p) ((p) & 0xff) |
|
#define BDC_U2T(p) (((p) & 0xff) << 8) |
|
#define BDC_U1T_MASK 0xff |
|
|
|
/* USBPM2 */ |
|
/* Hardware LPM Enable */ |
|
#define BDC_HLE BIT(16) |
|
|
|
/* BDC Status and Control */ |
|
#define BDC_COP_RST (1 << 29) |
|
#define BDC_COP_RUN (2 << 29) |
|
#define BDC_COP_STP (4 << 29) |
|
|
|
#define BDC_COP_MASK (BDC_COP_RST|BDC_COP_RUN|BDC_COP_STP) |
|
|
|
#define BDC_COS BIT(28) |
|
#define BDC_CSTS(p) (((p) & (0x7 << 20)) >> 20) |
|
#define BDC_MASK_MCW BIT(7) |
|
#define BDC_GIE BIT(1) |
|
#define BDC_GIP BIT(0) |
|
|
|
#define BDC_HLT 1 |
|
#define BDC_NOR 2 |
|
#define BDC_OIP 7 |
|
|
|
/* Buffer descriptor and Status report bit fields and masks */ |
|
#define BD_TYPE_BITMASK (0xf) |
|
#define BD_CHAIN 0xf |
|
|
|
#define BD_TFS_SHIFT 4 |
|
#define BD_SOT BIT(26) |
|
#define BD_EOT BIT(27) |
|
#define BD_ISP BIT(29) |
|
#define BD_IOC BIT(30) |
|
#define BD_SBF BIT(31) |
|
|
|
#define BD_INTR_TARGET(p) (((p) & 0x1f) << 27) |
|
|
|
#define BDC_SRR_RWS BIT(4) |
|
#define BDC_SRR_RST BIT(3) |
|
#define BDC_SRR_ISR BIT(2) |
|
#define BDC_SRR_IE BIT(1) |
|
#define BDC_SRR_IP BIT(0) |
|
#define BDC_SRR_EPI(p) (((p) & (0xff << 24)) >> 24) |
|
#define BDC_SRR_DPI(p) (((p) & (0xff << 16)) >> 16) |
|
#define BDC_SRR_DPI_MASK 0x00ff0000 |
|
|
|
#define MARK_CHAIN_BD (BD_CHAIN|BD_EOT|BD_SOT) |
|
|
|
/* Control transfer BD specific fields */ |
|
#define BD_DIR_IN BIT(25) |
|
|
|
#define BDC_PTC_MASK 0xf0000000 |
|
|
|
/* status report defines */ |
|
#define SR_XSF 0 |
|
#define SR_USPC 4 |
|
#define SR_BD_LEN(p) ((p) & 0xffffff) |
|
|
|
#define XSF_SUCC 0x1 |
|
#define XSF_SHORT 0x3 |
|
#define XSF_BABB 0x4 |
|
#define XSF_SETUP_RECV 0x6 |
|
#define XSF_DATA_START 0x7 |
|
#define XSF_STATUS_START 0x8 |
|
|
|
#define XSF_STS(p) (((p) >> 28) & 0xf) |
|
|
|
/* Transfer BD fields */ |
|
#define BD_LEN(p) ((p) & 0x1ffff) |
|
#define BD_LTF BIT(25) |
|
#define BD_TYPE_DS 0x1 |
|
#define BD_TYPE_SS 0x2 |
|
|
|
#define BDC_EP_ENABLED BIT(0) |
|
#define BDC_EP_STALL BIT(1) |
|
#define BDC_EP_STOP BIT(2) |
|
|
|
/* One BD can transfer max 65536 bytes */ |
|
#define BD_MAX_BUFF_SIZE (1 << 16) |
|
/* Maximum bytes in one XFR, Refer to BDC spec */ |
|
#define MAX_XFR_LEN 16777215 |
|
|
|
/* defines for Force Header command */ |
|
#define DEV_NOTF_TYPE 6 |
|
#define FWK_SUBTYPE 1 |
|
#define TRA_PACKET 4 |
|
|
|
#define to_bdc_ep(e) container_of(e, struct bdc_ep, usb_ep) |
|
#define to_bdc_req(r) container_of(r, struct bdc_req, usb_req) |
|
#define gadget_to_bdc(g) container_of(g, struct bdc, gadget) |
|
|
|
/* FUNCTION WAKE DEV NOTIFICATION interval, USB3 spec table 8.13 */ |
|
#define BDC_TNOTIFY 2500 /*in ms*/ |
|
/* Devstatus bitfields */ |
|
#define REMOTE_WAKEUP_ISSUED BIT(16) |
|
#define DEVICE_SUSPENDED BIT(17) |
|
#define FUNC_WAKE_ISSUED BIT(18) |
|
#define REMOTE_WAKE_ENABLE (1 << USB_DEVICE_REMOTE_WAKEUP) |
|
|
|
/* On disconnect, preserve these bits and clear rest */ |
|
#define DEVSTATUS_CLEAR (1 << USB_DEVICE_SELF_POWERED) |
|
/* Hardware and software Data structures */ |
|
|
|
/* Endpoint bd: buffer descriptor */ |
|
struct bdc_bd { |
|
__le32 offset[4]; |
|
}; |
|
|
|
/* Status report in Status report ring(srr) */ |
|
struct bdc_sr { |
|
__le32 offset[4]; |
|
}; |
|
|
|
/* bd_table: contiguous bd's in a table */ |
|
struct bd_table { |
|
struct bdc_bd *start_bd; |
|
/* dma address of start bd of table*/ |
|
dma_addr_t dma; |
|
}; |
|
|
|
/* |
|
* Each endpoint has a bdl(buffer descriptor list), bdl consists of 1 or more bd |
|
* table's chained to each other through a chain bd, every table has equal |
|
* number of bds. the software uses bdi(bd index) to refer to particular bd in |
|
* the list. |
|
*/ |
|
struct bd_list { |
|
/* Array of bd table pointers*/ |
|
struct bd_table **bd_table_array; |
|
/* How many tables chained to each other */ |
|
int num_tabs; |
|
/* Max_bdi = num_tabs * num_bds_table - 1 */ |
|
int max_bdi; |
|
/* current enq bdi from sw point of view */ |
|
int eqp_bdi; |
|
/* current deq bdi from sw point of view */ |
|
int hwd_bdi; |
|
/* numbers of bds per table */ |
|
int num_bds_table; |
|
}; |
|
|
|
struct bdc_req; |
|
|
|
/* Representation of a transfer, one transfer can have multiple bd's */ |
|
struct bd_transfer { |
|
struct bdc_req *req; |
|
/* start bd index */ |
|
int start_bdi; |
|
/* this will be the next hw dqp when this transfer completes */ |
|
int next_hwd_bdi; |
|
/* number of bds in this transfer */ |
|
int num_bds; |
|
}; |
|
|
|
/* |
|
* Representation of a gadget request, every gadget request is contained |
|
* by 1 bd_transfer. |
|
*/ |
|
struct bdc_req { |
|
struct usb_request usb_req; |
|
struct list_head queue; |
|
struct bdc_ep *ep; |
|
/* only one Transfer per request */ |
|
struct bd_transfer bd_xfr; |
|
int epnum; |
|
}; |
|
|
|
/* scratchpad buffer needed by bdc hardware */ |
|
struct bdc_scratchpad { |
|
dma_addr_t sp_dma; |
|
void *buff; |
|
u32 size; |
|
}; |
|
|
|
/* endpoint representation */ |
|
struct bdc_ep { |
|
struct usb_ep usb_ep; |
|
struct list_head queue; |
|
struct bdc *bdc; |
|
u8 ep_type; |
|
u8 dir; |
|
u8 ep_num; |
|
const struct usb_ss_ep_comp_descriptor *comp_desc; |
|
const struct usb_endpoint_descriptor *desc; |
|
unsigned int flags; |
|
char name[20]; |
|
/* endpoint bd list*/ |
|
struct bd_list bd_list; |
|
/* |
|
* HW generates extra event for multi bd tranfers, this flag helps in |
|
* ignoring the extra event |
|
*/ |
|
bool ignore_next_sr; |
|
}; |
|
|
|
/* bdc cmmand parameter structure */ |
|
struct bdc_cmd_params { |
|
u32 param2; |
|
u32 param1; |
|
u32 param0; |
|
}; |
|
|
|
/* status report ring(srr), currently one srr is supported for entire system */ |
|
struct srr { |
|
struct bdc_sr *sr_bds; |
|
u16 eqp_index; |
|
u16 dqp_index; |
|
dma_addr_t dma_addr; |
|
}; |
|
|
|
/* EP0 states */ |
|
enum bdc_ep0_state { |
|
WAIT_FOR_SETUP = 0, |
|
WAIT_FOR_DATA_START, |
|
WAIT_FOR_DATA_XMIT, |
|
WAIT_FOR_STATUS_START, |
|
WAIT_FOR_STATUS_XMIT, |
|
STATUS_PENDING |
|
}; |
|
|
|
/* Link states */ |
|
enum bdc_link_state { |
|
BDC_LINK_STATE_U0 = 0x00, |
|
BDC_LINK_STATE_U3 = 0x03, |
|
BDC_LINK_STATE_RX_DET = 0x05, |
|
BDC_LINK_STATE_RESUME = 0x0f |
|
}; |
|
|
|
/* representation of bdc */ |
|
struct bdc { |
|
struct usb_gadget gadget; |
|
struct usb_gadget_driver *gadget_driver; |
|
struct device *dev; |
|
/* device lock */ |
|
spinlock_t lock; |
|
|
|
/* generic phy */ |
|
struct phy **phys; |
|
int num_phys; |
|
/* num of endpoints for a particular instantiation of IP */ |
|
unsigned int num_eps; |
|
/* |
|
* Array of ep's, it uses the same index covention as bdc hw i.e. |
|
* 1 for ep0, 2 for 1out,3 for 1in .... |
|
*/ |
|
struct bdc_ep **bdc_ep_array; |
|
void __iomem *regs; |
|
struct bdc_scratchpad scratchpad; |
|
u32 sp_buff_size; |
|
/* current driver supports 1 status ring */ |
|
struct srr srr; |
|
/* Last received setup packet */ |
|
struct usb_ctrlrequest setup_pkt; |
|
struct bdc_req ep0_req; |
|
struct bdc_req status_req; |
|
enum bdc_ep0_state ep0_state; |
|
bool delayed_status; |
|
bool zlp_needed; |
|
bool reinit; |
|
bool pullup; |
|
/* Bits 0-15 are standard and 16-31 for proprietary information */ |
|
u32 devstatus; |
|
int irq; |
|
void *mem; |
|
u32 dev_addr; |
|
/* DMA pools */ |
|
struct dma_pool *bd_table_pool; |
|
u8 test_mode; |
|
/* array of callbacks for various status report handlers */ |
|
void (*sr_handler[2])(struct bdc *, struct bdc_sr *); |
|
/* ep0 callback handlers */ |
|
void (*sr_xsf_ep0[3])(struct bdc *, struct bdc_sr *); |
|
/* ep0 response buffer for ch9 requests like GET_STATUS and SET_SEL */ |
|
unsigned char ep0_response_buff[EP0_RESPONSE_BUFF]; |
|
/* |
|
* Timer to check if host resumed transfer after bdc sent Func wake |
|
* notification packet after a remote wakeup. if not, then resend the |
|
* Func Wake packet every 2.5 secs. Refer to USB3 spec section 8.5.6.4 |
|
*/ |
|
struct delayed_work func_wake_notify; |
|
struct clk *clk; |
|
}; |
|
|
|
static inline u32 bdc_readl(void __iomem *base, u32 offset) |
|
{ |
|
return readl(base + offset); |
|
} |
|
|
|
static inline void bdc_writel(void __iomem *base, u32 offset, u32 value) |
|
{ |
|
writel(value, base + offset); |
|
} |
|
|
|
/* Buffer descriptor list operations */ |
|
void bdc_notify_xfr(struct bdc *bdc, u32 epnum); |
|
void bdc_softconn(struct bdc *bdc); |
|
void bdc_softdisconn(struct bdc *bdc); |
|
int bdc_run(struct bdc *bdc); |
|
int bdc_stop(struct bdc *bdc); |
|
int bdc_reset(struct bdc *bdc); |
|
int bdc_udc_init(struct bdc *bdc); |
|
void bdc_udc_exit(struct bdc *bdc); |
|
int bdc_reinit(struct bdc *bdc); |
|
|
|
/* Status report handlers */ |
|
/* Upstream port status change sr */ |
|
void bdc_sr_uspc(struct bdc *bdc, struct bdc_sr *sreport); |
|
/* transfer sr */ |
|
void bdc_sr_xsf(struct bdc *bdc, struct bdc_sr *sreport); |
|
/* EP0 XSF handlers */ |
|
void bdc_xsf_ep0_setup_recv(struct bdc *bdc, struct bdc_sr *sreport); |
|
void bdc_xsf_ep0_data_start(struct bdc *bdc, struct bdc_sr *sreport); |
|
void bdc_xsf_ep0_status_start(struct bdc *bdc, struct bdc_sr *sreport); |
|
|
|
#endif /* __LINUX_BDC_H__ */
|
|
|