708 lines
21 KiB
C
708 lines
21 KiB
C
|
/* SPDX-License-Identifier: GPL-2.0 */
|
||
|
/*
|
||
|
* USBHS-DEV device controller driver header file
|
||
|
*
|
||
|
* Copyright (C) 2023 Cadence.
|
||
|
*
|
||
|
* Author: Pawel Laszczak <pawell@cadence.com>
|
||
|
*/
|
||
|
|
||
|
#ifndef __LINUX_CDNS2_GADGET
|
||
|
#define __LINUX_CDNS2_GADGET
|
||
|
|
||
|
#include <linux/usb/gadget.h>
|
||
|
#include <linux/dma-direction.h>
|
||
|
|
||
|
/*
|
||
|
* USBHS register interface.
|
||
|
* This corresponds to the USBHS Device Controller Interface.
|
||
|
*/
|
||
|
|
||
|
/**
|
||
|
* struct cdns2_ep0_regs - endpoint 0 related registers.
|
||
|
* @rxbc: receive (OUT) 0 endpoint byte count register.
|
||
|
* @txbc: transmit (IN) 0 endpoint byte count register.
|
||
|
* @cs: 0 endpoint control and status register.
|
||
|
* @reserved1: reserved.
|
||
|
* @fifo: 0 endpoint fifo register.
|
||
|
* @reserved2: reserved.
|
||
|
* @setupdat: SETUP data register.
|
||
|
* @reserved4: reserved.
|
||
|
* @maxpack: 0 endpoint max packet size.
|
||
|
*/
|
||
|
struct cdns2_ep0_regs {
|
||
|
__u8 rxbc;
|
||
|
__u8 txbc;
|
||
|
__u8 cs;
|
||
|
__u8 reserved1[4];
|
||
|
__u8 fifo;
|
||
|
__le32 reserved2[94];
|
||
|
__u8 setupdat[8];
|
||
|
__u8 reserved4[88];
|
||
|
__u8 maxpack;
|
||
|
} __packed __aligned(4);
|
||
|
|
||
|
/* EP0CS - bitmasks. */
|
||
|
/* Endpoint 0 stall bit for status stage. */
|
||
|
#define EP0CS_STALL BIT(0)
|
||
|
/* HSNAK bit. */
|
||
|
#define EP0CS_HSNAK BIT(1)
|
||
|
/* IN 0 endpoint busy bit. */
|
||
|
#define EP0CS_TXBSY_MSK BIT(2)
|
||
|
/* OUT 0 endpoint busy bit. */
|
||
|
#define EP0CS_RXBSY_MSK BIT(3)
|
||
|
/* Send STALL in the data stage phase. */
|
||
|
#define EP0CS_DSTALL BIT(4)
|
||
|
/* SETUP buffer content was changed. */
|
||
|
#define EP0CS_CHGSET BIT(7)
|
||
|
|
||
|
/* EP0FIFO - bitmasks. */
|
||
|
/* Direction. */
|
||
|
#define EP0_FIFO_IO_TX BIT(4)
|
||
|
/* FIFO auto bit. */
|
||
|
#define EP0_FIFO_AUTO BIT(5)
|
||
|
/* FIFO commit bit. */
|
||
|
#define EP0_FIFO_COMMIT BIT(6)
|
||
|
/* FIFO access bit. */
|
||
|
#define EP0_FIFO_ACCES BIT(7)
|
||
|
|
||
|
/**
|
||
|
* struct cdns2_epx_base - base endpoint registers.
|
||
|
* @rxbc: OUT endpoint byte count register.
|
||
|
* @rxcon: OUT endpoint control register.
|
||
|
* @rxcs: OUT endpoint control and status register.
|
||
|
* @txbc: IN endpoint byte count register.
|
||
|
* @txcon: IN endpoint control register.
|
||
|
* @txcs: IN endpoint control and status register.
|
||
|
*/
|
||
|
struct cdns2_epx_base {
|
||
|
__le16 rxbc;
|
||
|
__u8 rxcon;
|
||
|
__u8 rxcs;
|
||
|
__le16 txbc;
|
||
|
__u8 txcon;
|
||
|
__u8 txcs;
|
||
|
} __packed __aligned(4);
|
||
|
|
||
|
/* rxcon/txcon - endpoint control register bitmasks. */
|
||
|
/* Endpoint buffering: 0 - single buffering ... 3 - quad buffering. */
|
||
|
#define EPX_CON_BUF GENMASK(1, 0)
|
||
|
/* Endpoint type. */
|
||
|
#define EPX_CON_TYPE GENMASK(3, 2)
|
||
|
/* Endpoint type: isochronous. */
|
||
|
#define EPX_CON_TYPE_ISOC 0x4
|
||
|
/* Endpoint type: bulk. */
|
||
|
#define EPX_CON_TYPE_BULK 0x8
|
||
|
/* Endpoint type: interrupt. */
|
||
|
#define EPX_CON_TYPE_INT 0xC
|
||
|
/* Number of packets per microframe. */
|
||
|
#define EPX_CON_ISOD GENMASK(5, 4)
|
||
|
#define EPX_CON_ISOD_SHIFT 0x4
|
||
|
/* Endpoint stall bit. */
|
||
|
#define EPX_CON_STALL BIT(6)
|
||
|
/* Endpoint enable bit.*/
|
||
|
#define EPX_CON_VAL BIT(7)
|
||
|
|
||
|
/* rxcs/txcs - endpoint control and status bitmasks. */
|
||
|
/* Data sequence error for the ISO endpoint. */
|
||
|
#define EPX_CS_ERR(p) ((p) & BIT(0))
|
||
|
|
||
|
/**
|
||
|
* struct cdns2_epx_regs - endpoint 1..15 related registers.
|
||
|
* @reserved: reserved.
|
||
|
* @ep: none control endpoints array.
|
||
|
* @reserved2: reserved.
|
||
|
* @endprst: endpoint reset register.
|
||
|
* @reserved3: reserved.
|
||
|
* @isoautoarm: ISO auto-arm register.
|
||
|
* @reserved4: reserved.
|
||
|
* @isodctrl: ISO control register.
|
||
|
* @reserved5: reserved.
|
||
|
* @isoautodump: ISO auto dump enable register.
|
||
|
* @reserved6: reserved.
|
||
|
* @rxmaxpack: receive (OUT) Max packet size register.
|
||
|
* @reserved7: reserved.
|
||
|
* @rxstaddr: receive (OUT) start address endpoint buffer register.
|
||
|
* @reserved8: reserved.
|
||
|
* @txstaddr: transmit (IN) start address endpoint buffer register.
|
||
|
* @reserved9: reserved.
|
||
|
* @txmaxpack: transmit (IN) Max packet size register.
|
||
|
*/
|
||
|
struct cdns2_epx_regs {
|
||
|
__le32 reserved[2];
|
||
|
struct cdns2_epx_base ep[15];
|
||
|
__u8 reserved2[290];
|
||
|
__u8 endprst;
|
||
|
__u8 reserved3[41];
|
||
|
__le16 isoautoarm;
|
||
|
__u8 reserved4[10];
|
||
|
__le16 isodctrl;
|
||
|
__le16 reserved5;
|
||
|
__le16 isoautodump;
|
||
|
__le32 reserved6;
|
||
|
__le16 rxmaxpack[15];
|
||
|
__le32 reserved7[65];
|
||
|
__le32 rxstaddr[15];
|
||
|
__u8 reserved8[4];
|
||
|
__le32 txstaddr[15];
|
||
|
__u8 reserved9[98];
|
||
|
__le16 txmaxpack[15];
|
||
|
} __packed __aligned(4);
|
||
|
|
||
|
/* ENDPRST - bitmasks. */
|
||
|
/* Endpoint number. */
|
||
|
#define ENDPRST_EP GENMASK(3, 0)
|
||
|
/* IN direction bit. */
|
||
|
#define ENDPRST_IO_TX BIT(4)
|
||
|
/* Toggle reset bit. */
|
||
|
#define ENDPRST_TOGRST BIT(5)
|
||
|
/* FIFO reset bit. */
|
||
|
#define ENDPRST_FIFORST BIT(6)
|
||
|
/* Toggle status and reset bit. */
|
||
|
#define ENDPRST_TOGSETQ BIT(7)
|
||
|
|
||
|
/**
|
||
|
* struct cdns2_interrupt_regs - USB interrupt related registers.
|
||
|
* @reserved: reserved.
|
||
|
* @usbirq: USB interrupt request register.
|
||
|
* @extirq: external interrupt request register.
|
||
|
* @rxpngirq: external interrupt request register.
|
||
|
* @reserved1: reserved.
|
||
|
* @usbien: USB interrupt enable register.
|
||
|
* @extien: external interrupt enable register.
|
||
|
* @reserved2: reserved.
|
||
|
* @usbivect: USB interrupt vector register.
|
||
|
*/
|
||
|
struct cdns2_interrupt_regs {
|
||
|
__u8 reserved[396];
|
||
|
__u8 usbirq;
|
||
|
__u8 extirq;
|
||
|
__le16 rxpngirq;
|
||
|
__le16 reserved1[4];
|
||
|
__u8 usbien;
|
||
|
__u8 extien;
|
||
|
__le16 reserved2[3];
|
||
|
__u8 usbivect;
|
||
|
} __packed __aligned(4);
|
||
|
|
||
|
/* EXTIRQ and EXTIEN - bitmasks. */
|
||
|
/* VBUS fault fall interrupt. */
|
||
|
#define EXTIRQ_VBUSFAULT_FALL BIT(0)
|
||
|
/* VBUS fault fall interrupt. */
|
||
|
#define EXTIRQ_VBUSFAULT_RISE BIT(1)
|
||
|
/* Wake up interrupt bit. */
|
||
|
#define EXTIRQ_WAKEUP BIT(7)
|
||
|
|
||
|
/* USBIEN and USBIRQ - bitmasks. */
|
||
|
/* SETUP data valid interrupt bit.*/
|
||
|
#define USBIRQ_SUDAV BIT(0)
|
||
|
/* Start-of-frame interrupt bit. */
|
||
|
#define USBIRQ_SOF BIT(1)
|
||
|
/* SETUP token interrupt bit. */
|
||
|
#define USBIRQ_SUTOK BIT(2)
|
||
|
/* USB suspend interrupt bit. */
|
||
|
#define USBIRQ_SUSPEND BIT(3)
|
||
|
/* USB reset interrupt bit. */
|
||
|
#define USBIRQ_URESET BIT(4)
|
||
|
/* USB high-speed mode interrupt bit. */
|
||
|
#define USBIRQ_HSPEED BIT(5)
|
||
|
/* Link Power Management interrupt bit. */
|
||
|
#define USBIRQ_LPM BIT(7)
|
||
|
|
||
|
#define USB_IEN_INIT (USBIRQ_SUDAV | USBIRQ_SUSPEND | USBIRQ_URESET \
|
||
|
| USBIRQ_HSPEED | USBIRQ_LPM)
|
||
|
/**
|
||
|
* struct cdns2_usb_regs - USB controller registers.
|
||
|
* @reserved: reserved.
|
||
|
* @lpmctrl: LPM control register.
|
||
|
* @lpmclock: LPM clock register.
|
||
|
* @reserved2: reserved.
|
||
|
* @endprst: endpoint reset register.
|
||
|
* @usbcs: USB control and status register.
|
||
|
* @frmnr: USB frame counter register.
|
||
|
* @fnaddr: function Address register.
|
||
|
* @clkgate: clock gate register.
|
||
|
* @fifoctrl: FIFO control register.
|
||
|
* @speedctrl: speed Control register.
|
||
|
* @sleep_clkgate: sleep Clock Gate register.
|
||
|
* @reserved3: reserved.
|
||
|
* @cpuctrl: microprocessor control register.
|
||
|
*/
|
||
|
struct cdns2_usb_regs {
|
||
|
__u8 reserved[4];
|
||
|
__u16 lpmctrl;
|
||
|
__u8 lpmclock;
|
||
|
__u8 reserved2[411];
|
||
|
__u8 endprst;
|
||
|
__u8 usbcs;
|
||
|
__le16 frmnr;
|
||
|
__u8 fnaddr;
|
||
|
__u8 clkgate;
|
||
|
__u8 fifoctrl;
|
||
|
__u8 speedctrl;
|
||
|
__u8 sleep_clkgate;
|
||
|
__u8 reserved3[533];
|
||
|
__u8 cpuctrl;
|
||
|
} __packed __aligned(4);
|
||
|
|
||
|
/* LPMCTRL - bitmasks. */
|
||
|
/* BESL (Best Effort Service Latency). */
|
||
|
#define LPMCTRLLL_HIRD GENMASK(7, 4)
|
||
|
/* Last received Remote Wakeup field from LPM Extended Token packet. */
|
||
|
#define LPMCTRLLH_BREMOTEWAKEUP BIT(8)
|
||
|
/* Reflects value of the lpmnyet bit located in the usbcs[1] register. */
|
||
|
#define LPMCTRLLH_LPMNYET BIT(16)
|
||
|
|
||
|
/* LPMCLOCK - bitmasks. */
|
||
|
/*
|
||
|
* If bit is 1 the controller automatically turns off clock
|
||
|
* (utmisleepm goes to low), else the microprocessor should use
|
||
|
* sleep clock gate register to turn off clock.
|
||
|
*/
|
||
|
#define LPMCLOCK_SLEEP_ENTRY BIT(7)
|
||
|
|
||
|
/* USBCS - bitmasks. */
|
||
|
/* Send NYET handshake for the LPM transaction. */
|
||
|
#define USBCS_LPMNYET BIT(2)
|
||
|
/* Remote wake-up bit. */
|
||
|
#define USBCS_SIGRSUME BIT(5)
|
||
|
/* Software disconnect bit. */
|
||
|
#define USBCS_DISCON BIT(6)
|
||
|
/* Indicates that a wakeup pin resumed the controller. */
|
||
|
#define USBCS_WAKESRC BIT(7)
|
||
|
|
||
|
/* FIFOCTRL - bitmasks. */
|
||
|
/* Endpoint number. */
|
||
|
#define FIFOCTRL_EP GENMASK(3, 0)
|
||
|
/* Direction bit. */
|
||
|
#define FIFOCTRL_IO_TX BIT(4)
|
||
|
/* FIFO auto bit. */
|
||
|
#define FIFOCTRL_FIFOAUTO BIT(5)
|
||
|
/* FIFO commit bit. */
|
||
|
#define FIFOCTRL_FIFOCMIT BIT(6)
|
||
|
/* FIFO access bit. */
|
||
|
#define FIFOCTRL_FIFOACC BIT(7)
|
||
|
|
||
|
/* SPEEDCTRL - bitmasks. */
|
||
|
/* Device works in Full Speed. */
|
||
|
#define SPEEDCTRL_FS BIT(1)
|
||
|
/* Device works in High Speed. */
|
||
|
#define SPEEDCTRL_HS BIT(2)
|
||
|
/* Force FS mode. */
|
||
|
#define SPEEDCTRL_HSDISABLE BIT(7)
|
||
|
|
||
|
/* CPUCTRL- bitmasks. */
|
||
|
/* Controller reset bit. */
|
||
|
#define CPUCTRL_SW_RST BIT(1)
|
||
|
|
||
|
/**
|
||
|
* struct cdns2_adma_regs - ADMA controller registers.
|
||
|
* @conf: DMA global configuration register.
|
||
|
* @sts: DMA global Status register.
|
||
|
* @reserved1: reserved.
|
||
|
* @ep_sel: DMA endpoint select register.
|
||
|
* @ep_traddr: DMA endpoint transfer ring address register.
|
||
|
* @ep_cfg: DMA endpoint configuration register.
|
||
|
* @ep_cmd: DMA endpoint command register.
|
||
|
* @ep_sts: DMA endpoint status register.
|
||
|
* @reserved2: reserved.
|
||
|
* @ep_sts_en: DMA endpoint status enable register.
|
||
|
* @drbl: DMA doorbell register.
|
||
|
* @ep_ien: DMA endpoint interrupt enable register.
|
||
|
* @ep_ists: DMA endpoint interrupt status register.
|
||
|
* @axim_ctrl: AXI Master Control register.
|
||
|
* @axim_id: AXI Master ID register.
|
||
|
* @reserved3: reserved.
|
||
|
* @axim_cap: AXI Master Wrapper Extended Capability.
|
||
|
* @reserved4: reserved.
|
||
|
* @axim_ctrl0: AXI Master Wrapper Extended Capability Control Register 0.
|
||
|
* @axim_ctrl1: AXI Master Wrapper Extended Capability Control Register 1.
|
||
|
*/
|
||
|
struct cdns2_adma_regs {
|
||
|
__le32 conf;
|
||
|
__le32 sts;
|
||
|
__le32 reserved1[5];
|
||
|
__le32 ep_sel;
|
||
|
__le32 ep_traddr;
|
||
|
__le32 ep_cfg;
|
||
|
__le32 ep_cmd;
|
||
|
__le32 ep_sts;
|
||
|
__le32 reserved2;
|
||
|
__le32 ep_sts_en;
|
||
|
__le32 drbl;
|
||
|
__le32 ep_ien;
|
||
|
__le32 ep_ists;
|
||
|
__le32 axim_ctrl;
|
||
|
__le32 axim_id;
|
||
|
__le32 reserved3;
|
||
|
__le32 axim_cap;
|
||
|
__le32 reserved4;
|
||
|
__le32 axim_ctrl0;
|
||
|
__le32 axim_ctrl1;
|
||
|
};
|
||
|
|
||
|
#define CDNS2_ADMA_REGS_OFFSET 0x400
|
||
|
|
||
|
/* DMA_CONF - bitmasks. */
|
||
|
/* Reset USB device configuration. */
|
||
|
#define DMA_CONF_CFGRST BIT(0)
|
||
|
/* Singular DMA transfer mode.*/
|
||
|
#define DMA_CONF_DSING BIT(8)
|
||
|
/* Multiple DMA transfers mode.*/
|
||
|
#define DMA_CONF_DMULT BIT(9)
|
||
|
|
||
|
/* DMA_EP_CFG - bitmasks. */
|
||
|
/* Endpoint enable. */
|
||
|
#define DMA_EP_CFG_ENABLE BIT(0)
|
||
|
|
||
|
/* DMA_EP_CMD - bitmasks. */
|
||
|
/* Endpoint reset. */
|
||
|
#define DMA_EP_CMD_EPRST BIT(0)
|
||
|
/* Transfer descriptor ready. */
|
||
|
#define DMA_EP_CMD_DRDY BIT(6)
|
||
|
/* Data flush. */
|
||
|
#define DMA_EP_CMD_DFLUSH BIT(7)
|
||
|
|
||
|
/* DMA_EP_STS - bitmasks. */
|
||
|
/* Interrupt On Complete. */
|
||
|
#define DMA_EP_STS_IOC BIT(2)
|
||
|
/* Interrupt on Short Packet. */
|
||
|
#define DMA_EP_STS_ISP BIT(3)
|
||
|
/* Transfer descriptor missing. */
|
||
|
#define DMA_EP_STS_DESCMIS BIT(4)
|
||
|
/* TRB error. */
|
||
|
#define DMA_EP_STS_TRBERR BIT(7)
|
||
|
/* DMA busy bit. */
|
||
|
#define DMA_EP_STS_DBUSY BIT(9)
|
||
|
/* Current Cycle Status. */
|
||
|
#define DMA_EP_STS_CCS(p) ((p) & BIT(11))
|
||
|
/* OUT size mismatch. */
|
||
|
#define DMA_EP_STS_OUTSMM BIT(14)
|
||
|
/* ISO transmission error. */
|
||
|
#define DMA_EP_STS_ISOERR BIT(15)
|
||
|
|
||
|
/* DMA_EP_STS_EN - bitmasks. */
|
||
|
/* OUT transfer missing descriptor enable. */
|
||
|
#define DMA_EP_STS_EN_DESCMISEN BIT(4)
|
||
|
/* TRB enable. */
|
||
|
#define DMA_EP_STS_EN_TRBERREN BIT(7)
|
||
|
/* OUT size mismatch enable. */
|
||
|
#define DMA_EP_STS_EN_OUTSMMEN BIT(14)
|
||
|
/* ISO transmission error enable. */
|
||
|
#define DMA_EP_STS_EN_ISOERREN BIT(15)
|
||
|
|
||
|
/* DMA_EP_IEN - bitmasks. */
|
||
|
#define DMA_EP_IEN(index) (1 << (index))
|
||
|
#define DMA_EP_IEN_EP_OUT0 BIT(0)
|
||
|
#define DMA_EP_IEN_EP_IN0 BIT(16)
|
||
|
|
||
|
/* DMA_EP_ISTS - bitmasks. */
|
||
|
#define DMA_EP_ISTS(index) (1 << (index))
|
||
|
#define DMA_EP_ISTS_EP_OUT0 BIT(0)
|
||
|
#define DMA_EP_ISTS_EP_IN0 BIT(16)
|
||
|
|
||
|
#define gadget_to_cdns2_device(g) (container_of(g, struct cdns2_device, gadget))
|
||
|
#define ep_to_cdns2_ep(ep) (container_of(ep, struct cdns2_endpoint, endpoint))
|
||
|
|
||
|
/*-------------------------------------------------------------------------*/
|
||
|
#define TRBS_PER_SEGMENT 600
|
||
|
#define ISO_MAX_INTERVAL 8
|
||
|
#define MAX_TRB_LENGTH BIT(16)
|
||
|
#define MAX_ISO_SIZE 3076
|
||
|
/*
|
||
|
* To improve performance the TRB buffer pointers can't cross
|
||
|
* 4KB boundaries.
|
||
|
*/
|
||
|
#define TRB_MAX_ISO_BUFF_SHIFT 12
|
||
|
#define TRB_MAX_ISO_BUFF_SIZE BIT(TRB_MAX_ISO_BUFF_SHIFT)
|
||
|
/* How much data is left before the 4KB boundary? */
|
||
|
#define TRB_BUFF_LEN_UP_TO_BOUNDARY(addr) (TRB_MAX_ISO_BUFF_SIZE - \
|
||
|
((addr) & (TRB_MAX_ISO_BUFF_SIZE - 1)))
|
||
|
|
||
|
#if TRBS_PER_SEGMENT < 2
|
||
|
#error "Incorrect TRBS_PER_SEGMENT. Minimal Transfer Ring size is 2."
|
||
|
#endif
|
||
|
|
||
|
/**
|
||
|
* struct cdns2_trb - represent Transfer Descriptor block.
|
||
|
* @buffer: pointer to buffer data.
|
||
|
* @length: length of data.
|
||
|
* @control: control flags.
|
||
|
*
|
||
|
* This structure describes transfer block handled by DMA module.
|
||
|
*/
|
||
|
struct cdns2_trb {
|
||
|
__le32 buffer;
|
||
|
__le32 length;
|
||
|
__le32 control;
|
||
|
};
|
||
|
|
||
|
#define TRB_SIZE (sizeof(struct cdns2_trb))
|
||
|
/*
|
||
|
* These two extra TRBs are reserved for isochronous transfer
|
||
|
* to inject 0 length packet and extra LINK TRB to synchronize the ISO transfer.
|
||
|
*/
|
||
|
#define TRB_ISO_RESERVED 2
|
||
|
#define TR_SEG_SIZE (TRB_SIZE * (TRBS_PER_SEGMENT + TRB_ISO_RESERVED))
|
||
|
|
||
|
/* TRB bit mask. */
|
||
|
#define TRB_TYPE_BITMASK GENMASK(15, 10)
|
||
|
#define TRB_TYPE(p) ((p) << 10)
|
||
|
#define TRB_FIELD_TO_TYPE(p) (((p) & TRB_TYPE_BITMASK) >> 10)
|
||
|
|
||
|
/* TRB type IDs. */
|
||
|
/* Used for Bulk, Interrupt, ISOC, and control data stage. */
|
||
|
#define TRB_NORMAL 1
|
||
|
/* TRB for linking ring segments. */
|
||
|
#define TRB_LINK 6
|
||
|
|
||
|
/* Cycle bit - indicates TRB ownership by driver or hw. */
|
||
|
#define TRB_CYCLE BIT(0)
|
||
|
/*
|
||
|
* When set to '1', the device will toggle its interpretation of the Cycle bit.
|
||
|
*/
|
||
|
#define TRB_TOGGLE BIT(1)
|
||
|
/* Interrupt on short packet. */
|
||
|
#define TRB_ISP BIT(2)
|
||
|
/* Chain bit associate this TRB with next one TRB. */
|
||
|
#define TRB_CHAIN BIT(4)
|
||
|
/* Interrupt on completion. */
|
||
|
#define TRB_IOC BIT(5)
|
||
|
|
||
|
/* Transfer_len bitmasks. */
|
||
|
#define TRB_LEN(p) ((p) & GENMASK(16, 0))
|
||
|
#define TRB_BURST(p) (((p) << 24) & GENMASK(31, 24))
|
||
|
#define TRB_FIELD_TO_BURST(p) (((p) & GENMASK(31, 24)) >> 24)
|
||
|
|
||
|
/* Data buffer pointer bitmasks. */
|
||
|
#define TRB_BUFFER(p) ((p) & GENMASK(31, 0))
|
||
|
|
||
|
/*-------------------------------------------------------------------------*/
|
||
|
/* Driver numeric constants. */
|
||
|
|
||
|
/* Maximum address that can be assigned to device. */
|
||
|
#define USB_DEVICE_MAX_ADDRESS 127
|
||
|
|
||
|
/* One control and 15 IN and 15 OUT endpoints. */
|
||
|
#define CDNS2_ENDPOINTS_NUM 31
|
||
|
|
||
|
#define CDNS2_EP_ZLP_BUF_SIZE 512
|
||
|
|
||
|
/*-------------------------------------------------------------------------*/
|
||
|
/* Used structures. */
|
||
|
|
||
|
struct cdns2_device;
|
||
|
|
||
|
/**
|
||
|
* struct cdns2_ring - transfer ring representation.
|
||
|
* @trbs: pointer to transfer ring.
|
||
|
* @dma: dma address of transfer ring.
|
||
|
* @free_trbs: number of free TRBs in transfer ring.
|
||
|
* @pcs: producer cycle state.
|
||
|
* @ccs: consumer cycle state.
|
||
|
* @enqueue: enqueue index in transfer ring.
|
||
|
* @dequeue: dequeue index in transfer ring.
|
||
|
*/
|
||
|
struct cdns2_ring {
|
||
|
struct cdns2_trb *trbs;
|
||
|
dma_addr_t dma;
|
||
|
int free_trbs;
|
||
|
u8 pcs;
|
||
|
u8 ccs;
|
||
|
int enqueue;
|
||
|
int dequeue;
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* struct cdns2_endpoint - extended device side representation of USB endpoint.
|
||
|
* @endpoint: usb endpoint.
|
||
|
* @pending_list: list of requests queuing on transfer ring.
|
||
|
* @deferred_list: list of requests waiting for queuing on transfer ring.
|
||
|
* @pdev: device associated with endpoint.
|
||
|
* @name: a human readable name e.g. ep1out.
|
||
|
* @ring: transfer ring associated with endpoint.
|
||
|
* @ep_state: state of endpoint.
|
||
|
* @idx: index of endpoint in pdev->eps table.
|
||
|
* @dir: endpoint direction.
|
||
|
* @num: endpoint number (1 - 15).
|
||
|
* @type: set to bmAttributes & USB_ENDPOINT_XFERTYPE_MASK.
|
||
|
* @interval: interval between packets used for ISOC and Interrupt endpoint.
|
||
|
* @buffering: on-chip buffers assigned to endpoint.
|
||
|
* @trb_burst_size: number of burst used in TRB.
|
||
|
* @skip: Sometimes the controller cannot process isochronous endpoint ring
|
||
|
* quickly enough and it will miss some isoc tds on the ring and
|
||
|
* generate ISO transmition error.
|
||
|
* Driver sets skip flag when receive a ISO transmition error and
|
||
|
* process the missed TDs on the endpoint ring.
|
||
|
* @wa1_set: use WA1.
|
||
|
* @wa1_trb: TRB assigned to WA1.
|
||
|
* @wa1_trb_index: TRB index for WA1.
|
||
|
* @wa1_cycle_bit: correct cycle bit for WA1.
|
||
|
*/
|
||
|
struct cdns2_endpoint {
|
||
|
struct usb_ep endpoint;
|
||
|
struct list_head pending_list;
|
||
|
struct list_head deferred_list;
|
||
|
|
||
|
struct cdns2_device *pdev;
|
||
|
char name[20];
|
||
|
|
||
|
struct cdns2_ring ring;
|
||
|
|
||
|
#define EP_ENABLED BIT(0)
|
||
|
#define EP_STALLED BIT(1)
|
||
|
#define EP_STALL_PENDING BIT(2)
|
||
|
#define EP_WEDGE BIT(3)
|
||
|
#define EP_CLAIMED BIT(4)
|
||
|
#define EP_RING_FULL BIT(5)
|
||
|
#define EP_DEFERRED_DRDY BIT(6)
|
||
|
|
||
|
u32 ep_state;
|
||
|
|
||
|
u8 idx;
|
||
|
u8 dir;
|
||
|
u8 num;
|
||
|
u8 type;
|
||
|
int interval;
|
||
|
u8 buffering;
|
||
|
u8 trb_burst_size;
|
||
|
bool skip;
|
||
|
|
||
|
unsigned int wa1_set:1;
|
||
|
struct cdns2_trb *wa1_trb;
|
||
|
unsigned int wa1_trb_index;
|
||
|
unsigned int wa1_cycle_bit:1;
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* struct cdns2_request - extended device side representation of usb_request
|
||
|
* object.
|
||
|
* @request: generic usb_request object describing single I/O request.
|
||
|
* @pep: extended representation of usb_ep object.
|
||
|
* @trb: the first TRB association with this request.
|
||
|
* @start_trb: number of the first TRB in transfer ring.
|
||
|
* @end_trb: number of the last TRB in transfer ring.
|
||
|
* @list: used for queuing request in lists.
|
||
|
* @finished_trb: number of trb has already finished per request.
|
||
|
* @num_of_trb: how many trbs are associated with request.
|
||
|
*/
|
||
|
struct cdns2_request {
|
||
|
struct usb_request request;
|
||
|
struct cdns2_endpoint *pep;
|
||
|
struct cdns2_trb *trb;
|
||
|
int start_trb;
|
||
|
int end_trb;
|
||
|
struct list_head list;
|
||
|
int finished_trb;
|
||
|
int num_of_trb;
|
||
|
};
|
||
|
|
||
|
#define to_cdns2_request(r) (container_of(r, struct cdns2_request, request))
|
||
|
|
||
|
/* Stages used during enumeration process.*/
|
||
|
#define CDNS2_SETUP_STAGE 0x0
|
||
|
#define CDNS2_DATA_STAGE 0x1
|
||
|
#define CDNS2_STATUS_STAGE 0x2
|
||
|
|
||
|
/**
|
||
|
* struct cdns2_device - represent USB device.
|
||
|
* @dev: pointer to device structure associated whit this controller.
|
||
|
* @gadget: device side representation of the peripheral controller.
|
||
|
* @gadget_driver: pointer to the gadget driver.
|
||
|
* @lock: for synchronizing.
|
||
|
* @irq: interrupt line number.
|
||
|
* @regs: base address for registers
|
||
|
* @usb_regs: base address for common USB registers.
|
||
|
* @ep0_regs: base address for endpoint 0 related registers.
|
||
|
* @epx_regs: base address for all none control endpoint registers.
|
||
|
* @interrupt_regs: base address for interrupt handling related registers.
|
||
|
* @adma_regs: base address for ADMA registers.
|
||
|
* @eps_dma_pool: endpoint Transfer Ring pool.
|
||
|
* @setup: used while processing usb control requests.
|
||
|
* @ep0_preq: private request used while handling EP0.
|
||
|
* @ep0_stage: ep0 stage during enumeration process.
|
||
|
* @zlp_buf: zlp buffer.
|
||
|
* @dev_address: device address assigned by host.
|
||
|
* @eps: array of objects describing endpoints.
|
||
|
* @selected_ep: actually selected endpoint. It's used only to improve
|
||
|
* performance by limiting access to dma_ep_sel register.
|
||
|
* @is_selfpowered: device is self powered.
|
||
|
* @may_wakeup: allows device to remote wakeup the host.
|
||
|
* @status_completion_no_call: indicate that driver is waiting for status
|
||
|
* stage completion. It's used in deferred SET_CONFIGURATION request.
|
||
|
* @in_lpm: indicate the controller is in low power mode.
|
||
|
* @pending_status_wq: workqueue handling status stage for deferred requests.
|
||
|
* @pending_status_request: request for which status stage was deferred.
|
||
|
* @eps_supported: endpoints supported by controller in form:
|
||
|
* bit: 0 - ep0, 1 - epOut1, 2 - epIn1, 3 - epOut2 ...
|
||
|
* @burst_opt: array with the best burst size value for different TRB size.
|
||
|
* @onchip_tx_buf: size of transmit on-chip buffer in KB.
|
||
|
* @onchip_rx_buf: size of receive on-chip buffer in KB.
|
||
|
*/
|
||
|
struct cdns2_device {
|
||
|
struct device *dev;
|
||
|
struct usb_gadget gadget;
|
||
|
struct usb_gadget_driver *gadget_driver;
|
||
|
|
||
|
/* generic spin-lock for drivers */
|
||
|
spinlock_t lock;
|
||
|
int irq;
|
||
|
void __iomem *regs;
|
||
|
struct cdns2_usb_regs __iomem *usb_regs;
|
||
|
struct cdns2_ep0_regs __iomem *ep0_regs;
|
||
|
struct cdns2_epx_regs __iomem *epx_regs;
|
||
|
struct cdns2_interrupt_regs __iomem *interrupt_regs;
|
||
|
struct cdns2_adma_regs __iomem *adma_regs;
|
||
|
struct dma_pool *eps_dma_pool;
|
||
|
struct usb_ctrlrequest setup;
|
||
|
struct cdns2_request ep0_preq;
|
||
|
u8 ep0_stage;
|
||
|
void *zlp_buf;
|
||
|
u8 dev_address;
|
||
|
struct cdns2_endpoint eps[CDNS2_ENDPOINTS_NUM];
|
||
|
u32 selected_ep;
|
||
|
bool is_selfpowered;
|
||
|
bool may_wakeup;
|
||
|
bool status_completion_no_call;
|
||
|
bool in_lpm;
|
||
|
struct work_struct pending_status_wq;
|
||
|
struct usb_request *pending_status_request;
|
||
|
u32 eps_supported;
|
||
|
u8 burst_opt[MAX_ISO_SIZE + 1];
|
||
|
|
||
|
/*in KB */
|
||
|
u16 onchip_tx_buf;
|
||
|
u16 onchip_rx_buf;
|
||
|
};
|
||
|
|
||
|
#define CDNS2_IF_EP_EXIST(pdev, ep_num, dir) \
|
||
|
((pdev)->eps_supported & \
|
||
|
(BIT(ep_num) << ((dir) ? 0 : 16)))
|
||
|
|
||
|
dma_addr_t cdns2_trb_virt_to_dma(struct cdns2_endpoint *pep,
|
||
|
struct cdns2_trb *trb);
|
||
|
void cdns2_pending_setup_status_handler(struct work_struct *work);
|
||
|
void cdns2_select_ep(struct cdns2_device *pdev, u32 ep);
|
||
|
struct cdns2_request *cdns2_next_preq(struct list_head *list);
|
||
|
struct usb_request *cdns2_gadget_ep_alloc_request(struct usb_ep *ep,
|
||
|
gfp_t gfp_flags);
|
||
|
void cdns2_gadget_ep_free_request(struct usb_ep *ep,
|
||
|
struct usb_request *request);
|
||
|
int cdns2_gadget_ep_dequeue(struct usb_ep *ep, struct usb_request *request);
|
||
|
void cdns2_gadget_giveback(struct cdns2_endpoint *pep,
|
||
|
struct cdns2_request *priv_req,
|
||
|
int status);
|
||
|
void cdns2_init_ep0(struct cdns2_device *pdev, struct cdns2_endpoint *pep);
|
||
|
void cdns2_ep0_config(struct cdns2_device *pdev);
|
||
|
void cdns2_handle_ep0_interrupt(struct cdns2_device *pdev, int dir);
|
||
|
void cdns2_handle_setup_packet(struct cdns2_device *pdev);
|
||
|
int cdns2_gadget_resume(struct cdns2_device *pdev, bool hibernated);
|
||
|
int cdns2_gadget_suspend(struct cdns2_device *pdev);
|
||
|
void cdns2_gadget_remove(struct cdns2_device *pdev);
|
||
|
int cdns2_gadget_init(struct cdns2_device *pdev);
|
||
|
void set_reg_bit_8(void __iomem *ptr, u8 mask);
|
||
|
int cdns2_halt_endpoint(struct cdns2_device *pdev, struct cdns2_endpoint *pep,
|
||
|
int value);
|
||
|
|
||
|
#endif /* __LINUX_CDNS2_GADGET */
|