/*
 * Copyright (c) 2018-2020, NVIDIA CORPORATION.  All rights reserved.
 *
 * NVIDIA CORPORATION and its licensors retain all intellectual property
 * and proprietary rights in and to this software, related documentation
 * and any modifications thereto.  Any use, reproduction, disclosure or
 * distribution of this software and related documentation without an express
 * license agreement from NVIDIA CORPORATION is strictly prohibited.
 */
#ifndef __USBH_PROTOCOL_H
#define __USBH_PROTOCOL_H

#include <stdint.h>
#include <tegrabl_dmamap.h>

#define MAX_DEVICE_SLOTS	5

/* USB Class codes */
#define USB_CLASS_MSD			0x08
#define USB_CLASS_HUB			0x09

/* USB Device protocol codes */
#define USB_HUB_HS_SINGLE_TT	0x1
#define USB_HUB_HS_MULTI_TT		0x2

/* Slot context */
#define SLOT_CTX_SPEED_OFFSET				20
#define SLOT_CTX_ENTRIES_OFFSET				27
#define SLOT_CTX_ROOT_HUB_PORT_NUM_OFFSET	16
#define SLOT_CTX_NUM_HUB_PORTS_OFFSET		24

/* Endpoint context */
#define EP_CTX_EP_TYPE_OFFSET				3
#define EP_CTX_ERR_COUNT_OFFSET				1
#define EP_CTX_MAX_PKT_SIZE_OFFSET			16

struct setup_trb {
	uint32_t bmRequestType:8;   /* Request Type */
	uint32_t bmRequest:8;   /* Request */
	uint32_t wValue:16; /* value */

	uint32_t wIndex:16; /* Index */
	uint32_t wLength:16;    /* Length */

	uint32_t trb_tfr_len:17;    /* Always 8 */
	uint32_t rsvd0:5;   /* Reserved */
	uint32_t interrupter_target:10; /* Interrupter Target */

	uint32_t cycle_bit:1;   /* cycle bit */
	uint32_t rsvd1:4;   /* Reserved */
	uint32_t IOC:1; /* Interrupt On Completion */
	uint32_t IDT:1; /* Immediate Data */
	uint32_t rsvd2:3;   /* Reserved */
	uint32_t trb_type:6;    /* TRB Type */
	uint32_t TRT:2; /* Transfer Type */
	uint32_t rsvd3:14;  /* Reserved */
};

struct data_trb {
	uint32_t data_buffer_lo:32; /* Data buffer Lo ptr */
	uint32_t data_buffer_hi:32; /* Data buffer Hi Ptr */

	uint32_t trb_tfr_len:17;    /* Always 8 */
	uint32_t td_size:5; /* TD Size */
	uint32_t interrupter_target:10; /* Interrupter Target */

	uint32_t cycle_bit:1;   /* cycle bit */
	uint32_t ENT:1; /* Evaluate Next TRB */
	uint32_t ISP:1; /* Interrupt-on Short Packet */
	uint32_t NS:1;  /* No Snoop */
	uint32_t CH:1;  /* Chain bit */
	uint32_t IOC:1; /* Interrupt On Completion */
	uint32_t IDT:1; /* Immediate Data */
	uint32_t rsvd2:3;   /* Reserved */
	uint32_t trb_type:6;    /* TRB Type */
	uint32_t DIR:1; /* Data transfer direction */
	uint32_t rsvd3:15;  /* Reserved */
};

struct status_trb {
	uint32_t rsvd0:32;  /* Rsvd */
	uint32_t rsvd1:32;  /* Rsvd */

	uint32_t rsvd2:22;  /* Rsvd . */
	uint32_t interrupter_target:10; /* Interrupter Target */

	uint32_t cycle_bit:1;   /* cycle bit */
	uint32_t ENT:1; /* Evaluate Next TRB */
	uint32_t rsvd3:2;   /* Rsvd */
	uint32_t CH:1;  /* Chain bit */
	uint32_t IOC:1; /* Interrupt On Completion */
	uint32_t rsvd4:4;   /* Reserved */
	uint32_t trb_type:6;    /* TRB Type */
	uint32_t DIR:1; /* Data transfer direction */
	uint32_t rsvd5:15;  /* Reserved */
};

struct normal_trb {
	uint32_t data_buffer_lo:32; /* Data buffer Lo ptr */
	uint32_t data_buffer_hi:32; /* Data buffer Hi Ptr */
	uint32_t trb_tfr_len:17;    /* 0 - 65535 */
	uint32_t td_size:5; /* TD Size */
	uint32_t interrupter_target:10; /* Interrupter Target */
	uint32_t cycle_bit:1;   /* cycle bit */
	uint32_t ENT:1; /* Evaluate Next TRB */
	uint32_t ISP:1; /* Interrupt-on Short Packet */
	uint32_t NS:1;  /* No Snoop */
	uint32_t CH:1;  /* Chain bit */
	uint32_t IOC:1; /* Interrupt On Completion */
	uint32_t IDT:1; /* Immediate Data */
	uint32_t rsvd2:2;   /* Reserved */
	uint32_t BEI:1; /* Block Event Interrupt */
	uint32_t trb_type:6;    /* TRB Type */
	uint32_t rsvd3:16;  /* Reserved */
};

struct event_trb {
	uint32_t data_buffer_lo:32; /* Data buffer Lo ptr */
	uint32_t data_buffer_hi:32; /* Data buffer Hi Ptr */
	uint32_t trb_tfr_len:24;    /* TRB Transfer Length */
	uint32_t compl_code:8;  /* Completion Code */
	uint32_t cycle_bit:1;   /* cycle bit */
	uint32_t rsvd1:1;   /* Reserved */
	uint32_t evt_data:1;    /* Event Data, when set generated by event TRB */
	uint32_t rsvd2:7;   /* Reserved */
	uint32_t trb_type:6;    /* TRB Type */
	uint32_t ep_id:5;   /* Endpoint ID */
	uint32_t rsvd3:3;   /* Reserved */
	uint32_t slot_id:8; /* Slot ID */
};

/* packing is required to avoid structure padding by compiler */
struct usb_device_desc {
	uint8_t bLength;    /* 12h Size of this descriptor in bytes */
	uint8_t bDescriptorType;    /* 01h DEVICE descriptor type */
	/* USB Specification Release Number in Binary-Coded Decimal */
	uint16_t bcdUSB;
	/* (i.e. 2.10 = 210h). This field identifies the release of the USB */
	/* Specification with which the device and is descriptors are compliant */
	/* 00h Class is specified in the interface descriptor */
	uint8_t bDeviceClass;
	/* 00h Subclass is specified in the interface descriptor */
	uint8_t bDeviceSubClass;
	/* 00h Protocol is specified in the interface descriptor */
	uint8_t bDeviceProtocol;
	/* ??h Maximum packet size for endpoint zero.
	 *     (only 8, 16, 32, or 64 are valid (08h, 10h, 20h, 40h)) */
	uint8_t bMaxPacketSize0;
	uint16_t idVendor;  /* ????h Vendor ID (assigned by the USB-IF) */
	/* ????h Product ID (assigned by the manufacturer) */
	uint16_t idProduct;
	/* ????h Device release number in binary-coded decimal */
	uint16_t bcdDevice;
	/* ??h Index of string descriptor describing the manufacturer */
	uint8_t iManufacturer;
	/* ??h Index of string descriptor describing this product */
	uint8_t iProduct;
	/* ??h Index of string descriptor describing the device serial number */
	uint8_t iSerialNumber;
	/* ??h Number of possible configurations */
	uint8_t bNumConfigurations;

};

/* USB_DT_CONFIG: Configuration descriptor information.
 *
 * USB_DT_OTHER_SPEED_CONFIG is the same descriptor, except that the
 * descriptor type is different.  Highspeed-capable devices can look
 * different depending on what speed they're currently running.  Only
 * devices with a USB_DT_DEVICE_QUALIFIER have any OTHER_SPEED_CONFIG
 * descriptors.
 */

/* packing is required to avoid structure padding by compiler */
struct usb_config_desc {
	uint8_t bLength;
	uint8_t bDescriptorType;

	uint16_t wTotalLength;
	uint8_t bNumInterfaces;
	uint8_t bConfigurationValue;
	uint8_t iConfiguration;
	uint8_t bmAttributes;
	uint8_t bMaxPower;
};

/* usb config descriptor struct size */
#define USB_CONFIG_DESC_SIZE    9

/* USB_DT_INTERFACE: Interface descriptor */
/* packing is required to avoid structure padding by compiler */
struct usb_intf_desc {
	uint8_t bLength;
	uint8_t bDescriptorType;

	uint8_t bInterfaceNumber;
	uint8_t bAlternateSetting;
	uint8_t bNumEndpoints;
	uint8_t bInterfaceClass;
	uint8_t bInterfaceSubClass;
	uint8_t bInterfaceProtocol;
	uint8_t iInterface;
};


/* USB_DT_ENDPOINT: Endpoint descriptor */
/* packing is required to avoid structure padding by compiler */
struct usb_endpoint_desc {
	uint8_t bLength;
	uint8_t bDescriptorType;

	uint8_t bEndpointAddress;
	uint8_t bmAttributes;
	uint16_t wMaxPacketSize;
	uint8_t bInterval;
};

/* USB_DT_HUB: Hub descriptor */
struct usb_hub_desc {
	uint8_t bDescLength;
	uint8_t bDescriptorType;
	uint8_t bNbrPorts;
	uint16_t wHubCharacteristics;
	uint8_t bPwrOn2PwrGood;
	uint8_t bHubContrCurrent;
	uint8_t bHubHdrDecLat;
	uint16_t wHubDelay;
	uint16_t DeviceRemovable;
};

struct epdw0 {
	uint32_t ep_state:3;    /* Endpoint State */
	uint32_t res0:5;    /* Reserved */
	uint32_t mult:2;    /* Maximum number of burst within an interval */
	uint32_t max_pstreams:5;    /* Maximum number of Primary Stream IDs */
	uint32_t LSA:1; /* Linear Steram Array */
	uint32_t interval:8;    /* Interval between requests */
	uint32_t res1:8;    /* Reserved */
};

struct epdw1 {
	uint32_t res0:1;    /* Reserved */
	uint32_t cerr:2;    /* USB bus errors count */
	uint32_t ep_type:3; /* Endpoint Type */
	uint32_t res1:1;    /* Reserved */
	uint32_t hid:1; /* Host Initiated Stream  */
	uint32_t max_burst_size:8;  /* maximum number of bursts per scheduling  */
	uint32_t max_packet_size:16;    /* maximum packet size */
};

struct epdw2 {
	uint32_t DCS:1; /* Dequeue Cycle */
	uint32_t res0:3;    /* Reserved */
	uint32_t tr_dequeue_ptr_lo:28;
	/* : LSB of transfer ring dequeue pointer  */
};

struct epdw3 {
	uint32_t tr_dequeue_ptr_hi; /* : MSB of transfer ring dequeue pointer  */
};

struct epdw4 {
	uint32_t average_trb_length:16; /* averagelen , bw calculation */
	uint32_t max_esit_payload:16;   /* used for ISO scheduling */
};

struct EP {
	struct epdw0 dw0;
	struct epdw1 dw1;
	struct epdw2 dw2;
	struct epdw3 dw3;
	struct epdw4 dw4;
	uint32_t rsvd[11];
};
struct EP_COMMON {
	uint32_t field[16];
};
struct ctrl_ctx {
	uint32_t drop_flags;
	uint32_t add_flags;
	uint32_t rsvd[14];
};
struct slot_ctx {
	uint32_t info[2];
	uint32_t tt_info;
	uint32_t state;
	uint32_t rsvd[12];
};
struct ep_ctx {
	uint32_t info[2];
	uint64_t deq_ptr;
	uint32_t payload;
	uint32_t rsvd[11];
};

struct TRB {
	uint32_t field[4];
};

enum xhci_ring_type {
	TYPE_EVENT = 1,
	TYPE_COMMAND,
	TYPE_TX,
};

/* Define Endpoint Type */
enum xhci_endpoint_type {
	EP_TYPE_NOT_VALID = 0,
	EP_TYPE_ISOCH_OUT,
	EP_TYPE_BULK_OUT,
	EP_TYPE_INTERRUPT_OUT,
	EP_TYPE_CONTROL_BI,
	EP_TYPE_ISOCH_IN,
	EP_TYPE_BULK_IN,
	EP_TYPE_INTERRUPT_IN,
};

/* Define Endpoint State */
enum xhci_endpoint_state {
	EP_STATE_DISABLED = 0,
	EP_STATE_RUNNING,
	EP_STATE_HALTED,
	EP_STATE_STOPPED,
	EP_STATE_ERROR,
};

enum {
	XUSB_STATUS_WORKQ_SUBMITTED = 1,
	XUSB_STATUS_COMPQPOLL_START,
	XUSB_STATUS_COMPQPOLL_ERROR,
	XUSB_STATUS_COMPQPOLL_END,
	XUSB_STATUS_EVENTQPOLL_START,
	XUSB_STATUS_EVENTQPOLL_ERROR,
	XUSB_STATUS_EVENTQPOLL_END,
};

enum {
	INTERFACE_CLASS_MASS_STORAGE = 0x08,
	INTERFACE_PROTOCOL_BULK_ONLY_TRANSPORT = 0x50
};

enum {
	USB_EDP_DESC_SIZE = 7,
	USB_INTF_DESC_SIZE = 9,
};

#define ENDPOINT_DESC_ATTRIBUTES_BULK_TYPE  0x2
#define ENDPOINT_DESC_ATTRIBUTES_INTERRUPT_TYPE  0x3
#define ENDPOINT_DESC_ATTRIBUTES_TRANSFER_TYPE_MASK  0x3
#define ENDPOINT_DESC_ADDRESS_DIR_MASK  0x80
#define ENDPOINT_DESC_ADDRESS_DIR_OUT   0x00
#define ENDPOINT_DESC_ADDRESS_DIR_IN    0x80
#define ENDPOINT_DESC_ADDRESS_ENDPOINT_MASK 0x0f

/* Defines TRT Types */
enum trt_type {
	TRT_NO_DATA = 0,
	TRT_RSVD,
	TRT_OUT_DATA,
	TRT_IN_DATA,
};

/* Defines TRB Completion Codes */
enum {
	COMPLQCODE_INVALID = 0,
	COMPLQCODE_SUCCESS,
	COMPLQCODE_DATA_BUF_ERR,
	COMPLQCODE_BABBLE_ERR,
	COMPLQCODE_USB_TRANS_ERR,
	COMPLQCODE_TRB_ERR,
	COMPLQCODE_STALL_ERR,
	COMPLQCODE_RESOURCE_ERR,
	COMPLQCODE_BW_ERR,
	COMPLQCODE_NO_SLOTS_ERR,
	COMPLQCODE_INV_STREAM_TYPE_ERR,
	COMPLQCODE_SLOT_NOT_EN_ERR,
	COMPLQCODE_EP_NOT_EN_ERR,
	COMPLQCODE_SHORT_PKT,
	COMPLQCODE_RING_UNDERRUN,
	COMPLQCODE_RING_OVERRUN,
	COMPLQCODE_VF_EVT_RING_FULL_ERR,
	COMPLQCODE_PARAM_ERROR,
	COMPLQCODE_BW_OVERRUN,
	COMPLQCODE_CTX_STATE_ERR,
	COMPLQCODE_NO_PING_RSP_ERR,
	COMPLQCODE_EVT_RING_FULL_ERR,
	COMPLQCODE_MISS_SVC_ERR,
	COMPLQCODE_CMD_RING_STOPPED,
	COMPLQCODE_CMD_ABRT,
	COMPLQCODE_STOPPED,
	COMPLQCODE_STOPPED_LEN_INV,
	COMPLQCODE_CTRL_ABRT_ERR,
	COMPLQCODE_ISOCH_BUF_OVERRUN,
	COMPLQCODE_EVT_LOST_ERR,
	COMPLQCODE_UNDEF_ERR,
	COMPLQCODE_INV_STREAM_ID_ERR,
	COMPLQCODE_SEC_BW_ERR,
	COMPLQCODE_SPLIT_TRANS_ERR,
	COMPLQCODE_VENDOR_ERR = 192,
	COMPLQCODE_CTRL_SEQ_ERR = 223,
	COMPLQCODE_VENDOR_STATUS = 224,
};


/**
 * Defines the status from xusb
 */
struct usbh_status {
	/* Parameters specified by fuses or straps */
	uint8_t port_num;
	/* Parameters provided by the device */
	/* Sense key as returned by mode sense command */
	uint8_t sense_key;
	/* CSW status */
	uint32_t curr_csw_tag;
	uint32_t curr_cmd_csw_status;
	uint32_t curr_ep_bytes_not_transferred;
	/* Inquiry response */
	uint32_t peripheral_dev_typ;
	/* Read Fmt capacity */
	uint32_t num_blocks;
	/* Read Capacity response */
	uint32_t last_logical_blk_addr;
	uint32_t block_len_in_byte;
	/* Pointer to xusb_host_context */
	uint32_t xusb_host_context;

	uint32_t init_return_val;
	uint32_t read_page_return_val;
	uint32_t xusb_driver_status;
	/* Device status */
	uint32_t device_status;
	/* Endpoint status */
	uint32_t ep_status;
};

struct xhci_ring {
	struct TRB *first;
	struct TRB *enque_start_ptr;
	struct TRB *enque_curr_ptr;
	struct TRB *deque_ptr;
	dma_addr_t dma;
	enum xhci_ring_type type;
	uint32_t num_of_trbs;
	uint32_t cycle_state;
	uint32_t start_cycle_state;
};

/*
 * xusb_dev_priv - The private data structure for the USB/hub device.
 */
struct xusb_dev_priv {
	/* cmd/transfer/event rings */
	struct xhci_ring ep_ring[3];
	struct xhci_ring ep1_out_ring;
	struct xhci_ring ep1_in_ring;

	/* Endpoint data structure context */
	struct EP *dev_context;
	dma_addr_t dev_context_dma;
	struct EP *input_context;
	dma_addr_t input_context_dma;

	/* Copied from various device descriptors */
	struct {
		/* Current device address assigned to device by the host */
		uint8_t dev_addr;
		/* From the device descriptor */
		uint8_t bDeviceClass;
		uint8_t bDeviceProtocol;
		uint8_t bNumConfigurations;
		/* Vendor and Product ID */
		uint16_t vendor_id;
		uint16_t product_id;
		uint8_t bMaxPacketSize0;
		/* From the configuration descriptor */
		uint8_t bConfigurationValue;
		/* From the interface descriptor */
		uint8_t interface_indx;
		uint8_t class;
		uint8_t subclass;
		uint8_t protocol;
		/* From the endpoint descriptors */
		uint32_t bInterval;
		struct {
			uint16_t packet_size;
			uint8_t addr;
			/* OUT is indexed by 0 (direction out) and
			 * IN type is indexed by 1 (direction in) */
		} ep[2];
	} enum_dev;

	/* Port speed */
	uint32_t speed;
	/* Route string */
	uint8_t route_string;
};

/*
 * xusb_host_context - The context structure for the xusb host driver.
 */
struct xusb_host_context {
	uint64_t *dcbaa;
	struct xhci_ring cmd_ring;
	struct xhci_ring event_ring;

	struct xhci_erst_entry {
		uint64_t seg_addr;
		uint32_t seg_size;
		uint32_t rsvd;
	} *erst;

	/* Data buffer for host<->device handshaking*/
	uint32_t *xusb_data;
	dma_addr_t xusb_data_dma;

	/* Hub address */
	uint8_t hub_address;
	/* No of ports hub has */
	uint8_t hub_num_ports;
	/* Root port number */
	uint8_t root_port_number;
	/* Root port speed */
	uint8_t root_port_speed;
	/* Port Id */
	uint8_t port_id;
	/* Slot Id number */
	uint8_t slot_id;
	uint8_t hub_slot_id;

	/* Array of pointers to each USB device and pointer to current device*/
	struct xusb_dev_priv *dev_priv[MAX_DEVICE_SLOTS];
	struct xusb_dev_priv *curr_dev_priv;

	/* For all commands except read and write,
	 * the data buffer used to get data is BufferXusbData space else
	 * it is the address of the memory area passed from the top level flow */
	uint8_t *buffer_data;

	/* For logging useful info in Boot info table's SecondaryDevStatus field */
	struct xusb_status *xusb_bit_info;

	/* Completion code from handle_transfer_event */
	uint8_t comp_code;

	/* Required for Read command */
	uint8_t logical_blk_addr[4];
	uint8_t transfer_len[2];

	/* Current page under access in CSB space */
	uint32_t current_csb_page;

	/* Block size in Log2 scale */
	uint8_t block_size_log2;
	/* Page size in Log2 scale */
	uint8_t page_size_log2;
	uint32_t page_size;

	/* Holds the xusb Read start time */
	uint64_t read_start_time;
	/* Sequence no., for bulk out */
	uint32_t bulk_seq_num_out;
	/* Sequence no., for bulk In */
	uint32_t bulk_seq_num_in;
};

#endif
