blob: 9c2bc185071b1cacd7a3277b49d4be92b8790d02 [file] [log] [blame]
// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
/*
* Copyright (C) 2004-2013 Synopsys, Inc.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions, and the following disclaimer,
* without modification.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The names of the above-listed copyright holders may not be used
* to endorse or promote products derived from this software without
* specific prior written permission.
*
* ALTERNATIVELY, this software may be distributed under the terms of the
* GNU General Public License ("GPL") as published by the Free Software
* Foundation; either version 2 of the License, or (at your option) any
* later version.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS 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.
*/
#ifndef __DWC2_CORE_H__
#define __DWC2_CORE_H__
#include "diag_USB.h"
#include "hw.h"
#include <stddef.h>
#include "usb_typedefs.h"
#include "ch9.h"
#include "core.h"
#define ACPU_MEMMAP_USBAHB_REG_BASE MEMMAP_USB0_REG_BASE
#define MAX_DEVICE 16
/* Maximum number of Endpoints/HostChannels */
#define MAX_EPS_CHANNELS 16
/* Create various pipes... */
#define create_pipe(dev,endpoint) \
(((dev)->devnum << 8) | ((endpoint) << 15) | \
(dev)->maxpacketsize)
#define default_pipe(dev) ((dev)->speed << 26)
#define usb_sndctrlpipe(dev, endpoint) ((PIPE_CONTROL << 30) | \
create_pipe(dev, endpoint))
#define usb_rcvctrlpipe(dev, endpoint) ((PIPE_CONTROL << 30) | \
create_pipe(dev, endpoint) | \
USB_DIR_IN)
#define usb_sndisocpipe(dev, endpoint) ((PIPE_ISOCHRONOUS << 30) | \
create_pipe(dev, endpoint))
#define usb_rcvisocpipe(dev, endpoint) ((PIPE_ISOCHRONOUS << 30) | \
create_pipe(dev, endpoint) | \
USB_DIR_IN)
#define usb_sndbulkpipe(dev, endpoint) ((PIPE_BULK << 30) | \
create_pipe(dev, endpoint))
#define usb_rcvbulkpipe(dev, endpoint) ((PIPE_BULK << 30) | \
create_pipe(dev, endpoint) | \
USB_DIR_IN)
#define usb_sndintpipe(dev, endpoint) ((PIPE_INTERRUPT << 30) | \
create_pipe(dev, endpoint))
#define usb_rcvintpipe(dev, endpoint) ((PIPE_INTERRUPT << 30) | \
create_pipe(dev, endpoint) | \
USB_DIR_IN)
#define usb_snddefctrl(dev) ((PIPE_CONTROL << 30) | \
default_pipe(dev))
#define usb_rcvdefctrl(dev) ((PIPE_CONTROL << 30) | \
default_pipe(dev) | \
USB_DIR_IN)
/* Endpoint halt control/status */
#define usb_endpoint_out(ep_dir) (((ep_dir >> 7) & 1) ^ 1)
#define usb_endpoint_halt(dev, ep, out) ((dev)->halted[out] |= (1 << (ep)))
#define usb_endpoint_running(dev, ep, out) ((dev)->halted[out] &= ~(1 << (ep)))
#define usb_endpoint_halted(dev, ep, out) ((dev)->halted[out] & (1 << (ep)))
#define usb_pipeout(pipe) ((((pipe) >> 7) & 1) ^ 1)
#define usb_pipein(pipe) (((pipe) >> 7) & 1)
#define usb_pipedevice(pipe) (((pipe) >> 8) & 0x7f)
#define usb_pipe_endpdev(pipe) (((pipe) >> 8) & 0x7ff)
#define usb_pipeendpoint(pipe) (((pipe) >> 15) & 0xf)
#define usb_pipedata(pipe) (((pipe) >> 19) & 1)
#define usb_pipetype(pipe) (((pipe) >> 30) & 3)
#define usb_pipeisoc(pipe) (usb_pipetype((pipe)) == PIPE_ISOCHRONOUS)
#define usb_pipeint(pipe) (usb_pipetype((pipe)) == PIPE_INTERRUPT)
#define usb_pipecontrol(pipe) (usb_pipetype((pipe)) == PIPE_CONTROL)
#define usb_pipebulk(pipe) (usb_pipetype((pipe)) == PIPE_BULK)
/**
* struct dwc2_hw_params - Autodetected parameters.
*
* These parameters are the various parameters read from hardware
* registers during initialization. They typically contain the best
* supported or maximum value that can be configured in the
* corresponding dwc2_core_params value.
*
* The values that are not in dwc2_core_params are documented below.
*
* @op_mode: Mode of Operation
* 0 - HNP- and SRP-Capable OTG (Host & Device)
* 1 - SRP-Capable OTG (Host & Device)
* 2 - Non-HNP and Non-SRP Capable OTG (Host & Device)
* 3 - SRP-Capable Device
* 4 - Non-OTG Device
* 5 - SRP-Capable Host
* 6 - Non-OTG Host
* @arch: Architecture
* 0 - Slave only
* 1 - External DMA
* 2 - Internal DMA
* @ipg_isoc_en: This feature indicates that the controller supports
* the worst-case scenario of Rx followed by Rx
* Interpacket Gap (IPG) (32 bitTimes) as per the utmi
* specification for any token following ISOC OUT token.
* 0 - Don't support
* 1 - Support
* @power_optimized: Are power optimizations enabled?
* @num_dev_ep: Number of device endpoints available
* @num_dev_in_eps: Number of device IN endpoints available
* @num_dev_perio_in_ep: Number of device periodic IN endpoints
* available
* @dev_token_q_depth: Device Mode IN Token Sequence Learning Queue
* Depth
* 0 to 30
* @host_perio_tx_q_depth:
* Host Mode Periodic Request Queue Depth
* 2, 4 or 8
* @nperio_tx_q_depth:
* Non-Periodic Request Queue Depth
* 2, 4 or 8
* @hs_phy_type: High-speed PHY interface type
* 0 - High-speed interface not supported
* 1 - UTMI+
* 2 - ULPI
* 3 - UTMI+ and ULPI
* @fs_phy_type: Full-speed PHY interface type
* 0 - Full speed interface not supported
* 1 - Dedicated full speed interface
* 2 - FS pins shared with UTMI+ pins
* 3 - FS pins shared with ULPI pins
* @total_fifo_size: Total internal RAM for FIFOs (bytes)
* @hibernation: Is hibernation enabled?
* @utmi_phy_data_width: UTMI+ PHY data width
* 0 - 8 bits
* 1 - 16 bits
* 2 - 8 or 16 bits
* @snpsid: Value from SNPSID register
* @dev_ep_dirs: Direction of device endpoints (GHWCFG1)
* @g_tx_fifo_size: Power-on values of TxFIFO sizes
* @dma_desc_enable: When DMA mode is enabled, specifies whether to use
* address DMA mode or descriptor DMA mode for accessing
* the data FIFOs. The driver will automatically detect the
* value for this if none is specified.
* 0 - Address DMA
* 1 - Descriptor DMA (default, if available)
* @enable_dynamic_fifo: 0 - Use coreConsultant-specified FIFO size parameters
* 1 - Allow dynamic FIFO sizing (default, if available)
* @en_multiple_tx_fifo: Specifies whether dedicated per-endpoint transmit FIFOs
* are enabled for non-periodic IN endpoints in device
* mode.
* @host_nperio_tx_fifo_size: Number of 4-byte words in the non-periodic Tx FIFO
* in host mode when dynamic FIFO sizing is enabled
* 16 to 32768
* Actual maximum value is autodetected and also
* the default.
* @host_perio_tx_fifo_size: Number of 4-byte words in the periodic Tx FIFO in
* host mode when dynamic FIFO sizing is enabled
* 16 to 32768
* Actual maximum value is autodetected and also
* the default.
* @max_transfer_size: The maximum transfer size supported, in bytes
* 2047 to 65,535
* Actual maximum value is autodetected and also
* the default.
* @max_packet_count: The maximum number of packets in a transfer
* 15 to 511
* Actual maximum value is autodetected and also
* the default.
* @host_channels: The number of host channel registers to use
* 1 to 16
* Actual maximum value is autodetected and also
* the default.
* @dev_nperio_tx_fifo_size: Number of 4-byte words in the non-periodic Tx FIFO
* in device mode when dynamic FIFO sizing is enabled
* 16 to 32768
* Actual maximum value is autodetected and also
* the default.
* @i2c_enable: Specifies whether to use the I2Cinterface for a full
* speed PHY. This parameter is only applicable if phy_type
* is FS.
* 0 - No (default)
* 1 - Yes
* @acg_enable: For enabling Active Clock Gating in the controller
* 0 - Disable
* 1 - Enable
* @lpm_mode: For enabling Link Power Management in the controller
* 0 - Disable
* 1 - Enable
* @rx_fifo_size: Number of 4-byte words in the Rx FIFO when dynamic
* FIFO sizing is enabled 16 to 32768
* Actual maximum value is autodetected and also
* the default.
*/
struct dwc2_hw_params {
unsigned op_mode:3;
unsigned arch:2;
unsigned dma_desc_enable:1;
unsigned enable_dynamic_fifo:1;
unsigned en_multiple_tx_fifo:1;
unsigned rx_fifo_size:16;
unsigned host_nperio_tx_fifo_size:16;
unsigned dev_nperio_tx_fifo_size:16;
unsigned host_perio_tx_fifo_size:16;
unsigned nperio_tx_q_depth:3;
unsigned host_perio_tx_q_depth:3;
unsigned dev_token_q_depth:5;
unsigned max_transfer_size:26;
unsigned max_packet_count:11;
unsigned host_channels:5;
unsigned hs_phy_type:2;
unsigned fs_phy_type:2;
unsigned i2c_enable:1;
unsigned acg_enable:1;
unsigned num_dev_ep:4;
unsigned num_dev_in_eps : 4;
unsigned num_dev_perio_in_ep:4;
unsigned total_fifo_size:16;
unsigned power_optimized:1;
unsigned hibernation:1;
unsigned utmi_phy_data_width:2;
unsigned lpm_mode:1;
unsigned ipg_isoc_en:1;
u32 snpsid;
u32 dev_ep_dirs;
u32 g_tx_fifo_size[MAX_EPS_CHANNELS];
};
/**
* struct dwc2_hsotg - Holds the state of the driver, including the non-periodic
* and periodic schedules
*
* These are common for both host and peripheral modes:
*
* @dev: The struct device pointer
* @regs: Pointer to controller regs
* @hw_params: Parameters that were autodetected from the
* hardware registers
* @params: Parameters that define how the core should be configured
* @op_state: The operational State, during transitions (a_host=>
* a_peripheral and b_device=>b_host) this may not match
* the core, but allows the software to determine
* transitions
* @dr_mode: Requested mode of operation, one of following:
* - USB_DR_MODE_PERIPHERAL
* - USB_DR_MODE_HOST
* - USB_DR_MODE_OTG
* @hcd_enabled: Host mode sub-driver initialization indicator.
* @gadget_enabled: Peripheral mode sub-driver initialization indicator.
* @ll_hw_enabled: Status of low-level hardware resources.
* @hibernated: True if core is hibernated
* @frame_number: Frame number read from the core. For both device
* and host modes. The value ranges are from 0
* to HFNUM_MAX_FRNUM.
* @phy: The otg phy transceiver structure for phy control.
* @uphy: The otg phy transceiver structure for old USB phy
* control.
* @plat: The platform specific configuration data. This can be
* removed once all SoCs support usb transceiver.
* @supplies: Definition of USB power supplies
* @vbus_supply: Regulator supplying vbus.
* @phyif: PHY interface width
* @lock: Spinlock that protects all the driver data structures
* @priv: Stores a pointer to the struct usb_hcd
* @queuing_high_bandwidth: True if multiple packets of a high-bandwidth
* transfer are in process of being queued
* @srp_success: Stores status of SRP request in the case of a FS PHY
* with an I2C interface
* @wq_otg: Workqueue object used for handling of some interrupts
* @wf_otg: Work object for handling Connector ID Status Change
* interrupt
* @wkp_timer: Timer object for handling Wakeup Detected interrupt
* @lx_state: Lx state of connected device
* @gr_backup: Backup of global registers during suspend
* @dr_backup: Backup of device registers during suspend
* @hr_backup: Backup of host registers during suspend
* @needs_byte_swap: Specifies whether the opposite endianness.
*
* These are for host mode:
*
* @flags: Flags for handling root port state changes
* @flags.d32: Contain all root port flags
* @flags.b: Separate root port flags from each other
* @flags.b.port_connect_status_change: True if root port connect status
* changed
* @flags.b.port_connect_status: True if device connected to root port
* @flags.b.port_reset_change: True if root port reset status changed
* @flags.b.port_enable_change: True if root port enable status changed
* @flags.b.port_suspend_change: True if root port suspend status changed
* @flags.b.port_over_current_change: True if root port over current state
* changed.
* @flags.b.port_l1_change: True if root port l1 status changed
* @flags.b.reserved: Reserved bits of root port register
* @non_periodic_sched_inactive: Inactive QHs in the non-periodic schedule.
* Transfers associated with these QHs are not currently
* assigned to a host channel.
* @non_periodic_sched_active: Active QHs in the non-periodic schedule.
* Transfers associated with these QHs are currently
* assigned to a host channel.
* @non_periodic_qh_ptr: Pointer to next QH to process in the active
* non-periodic schedule
* @non_periodic_sched_waiting: Waiting QHs in the non-periodic schedule.
* Transfers associated with these QHs are not currently
* assigned to a host channel.
* @periodic_sched_inactive: Inactive QHs in the periodic schedule. This is a
* list of QHs for periodic transfers that are _not_
* scheduled for the next frame. Each QH in the list has an
* interval counter that determines when it needs to be
* scheduled for execution. This scheduling mechanism
* allows only a simple calculation for periodic bandwidth
* used (i.e. must assume that all periodic transfers may
* need to execute in the same frame). However, it greatly
* simplifies scheduling and should be sufficient for the
* vast majority of OTG hosts, which need to connect to a
* small number of peripherals at one time. Items move from
* this list to periodic_sched_ready when the QH interval
* counter is 0 at SOF.
* @periodic_sched_ready: List of periodic QHs that are ready for execution in
* the next frame, but have not yet been assigned to host
* channels. Items move from this list to
* periodic_sched_assigned as host channels become
* available during the current frame.
* @periodic_sched_assigned: List of periodic QHs to be executed in the next
* frame that are assigned to host channels. Items move
* from this list to periodic_sched_queued as the
* transactions for the QH are queued to the DWC_otg
* controller.
* @periodic_sched_queued: List of periodic QHs that have been queued for
* execution. Items move from this list to either
* periodic_sched_inactive or periodic_sched_ready when the
* channel associated with the transfer is released. If the
* interval for the QH is 1, the item moves to
* periodic_sched_ready because it must be rescheduled for
* the next frame. Otherwise, the item moves to
* periodic_sched_inactive.
* @split_order: List keeping track of channels doing splits, in order.
* @periodic_usecs: Total bandwidth claimed so far for periodic transfers.
* This value is in microseconds per (micro)frame. The
* assumption is that all periodic transfers may occur in
* the same (micro)frame.
* @hs_periodic_bitmap: Bitmap used by the microframe scheduler any time the
* host is in high speed mode; low speed schedules are
* stored elsewhere since we need one per TT.
* @periodic_qh_count: Count of periodic QHs, if using several eps. Used for
* SOF enable/disable.
* @free_hc_list: Free host channels in the controller. This is a list of
* struct dwc2_host_chan items.
* @periodic_channels: Number of host channels assigned to periodic transfers.
* Currently assuming that there is a dedicated host
* channel for each periodic transaction and at least one
* host channel is available for non-periodic transactions.
* @non_periodic_channels: Number of host channels assigned to non-periodic
* transfers
* @available_host_channels: Number of host channels available for the
* microframe scheduler to use
* @hc_ptr_array: Array of pointers to the host channel descriptors.
* Allows accessing a host channel descriptor given the
* host channel number. This is useful in interrupt
* handlers.
* @status_buf: Buffer used for data received during the status phase of
* a control transfer.
* @status_buf_dma: DMA address for status_buf
* @start_work: Delayed work for handling host A-cable connection
* @reset_work: Delayed work for handling a port reset
* @otg_port: OTG port number
* @frame_list: Frame list
* @frame_list_dma: Frame list DMA address
* @frame_list_sz: Frame list size
* @desc_gen_cache: Kmem cache for generic descriptors
* @desc_hsisoc_cache: Kmem cache for hs isochronous descriptors
* @unaligned_cache: Kmem cache for DMA mode to handle non-aligned buf
*
* These are for peripheral mode:
*
* @driver: USB gadget driver
* @dedicated_fifos: Set if the hardware has dedicated IN-EP fifos.
* @num_of_eps: Number of available EPs (excluding EP0)
* @debug_root: Root directrory for debugfs.
* @ep0_reply: Request used for ep0 reply.
* @ep0_buff: Buffer for EP0 reply data, if needed.
* @ctrl_buff: Buffer for EP0 control requests.
* @ctrl_req: Request for EP0 control packets.
* @ep0_state: EP0 control transfers state
* @test_mode: USB test mode requested by the host
* @remote_wakeup_allowed: True if device is allowed to wake-up host by
* remote-wakeup signalling
* @setup_desc_dma: EP0 setup stage desc chain DMA address
* @setup_desc: EP0 setup stage desc chain pointer
* @ctrl_in_desc_dma: EP0 IN data phase desc chain DMA address
* @ctrl_in_desc: EP0 IN data phase desc chain pointer
* @ctrl_out_desc_dma: EP0 OUT data phase desc chain DMA address
* @ctrl_out_desc: EP0 OUT data phase desc chain pointer
* @irq: Interrupt request line number
* @clk: Pointer to otg clock
* @reset: Pointer to dwc2 reset controller
* @reset_ecc: Pointer to dwc2 optional reset controller in Stratix10.
* @regset: A pointer to a struct debugfs_regset32, which contains
* a pointer to an array of register definitions, the
* array size and the base address where the register bank
* is to be found.
* @bus_suspended: True if bus is suspended
* @last_frame_num: Number of last frame. Range from 0 to 32768
* @frame_num_array: Used only if CONFIG_USB_DWC2_TRACK_MISSED_SOFS is
* defined, for missed SOFs tracking. Array holds that
* frame numbers, which not equal to last_frame_num +1
* @last_frame_num_array: Used only if CONFIG_USB_DWC2_TRACK_MISSED_SOFS is
* defined, for missed SOFs tracking.
* If current_frame_number != last_frame_num+1
* then last_frame_num added to this array
* @frame_num_idx: Actual size of frame_num_array and last_frame_num_array
* @dumped_frame_num_array: 1 - if missed SOFs frame numbers dumbed
* 0 - if missed SOFs frame numbers not dumbed
* @fifo_mem: Total internal RAM for FIFOs (bytes)
* @fifo_map: Each bit intend for concrete fifo. If that bit is set,
* then that fifo is used
* @gadget: Represents a usb slave device
* @connected: Used in slave mode. True if device connected with host
* @eps_in: The IN endpoints being supplied to the gadget framework
* @eps_out: The OUT endpoints being supplied to the gadget framework
* @new_connection: Used in host mode. True if there are new connected
* device
* @enabled: Indicates the enabling state of controller
*
*/
/* DWC OTG HW Release versions */
#define DWC2_CORE_REV_2_71a 0x4f54271a
#define DWC2_CORE_REV_2_72a 0x4f54272a
#define DWC2_CORE_REV_2_80a 0x4f54280a
#define DWC2_CORE_REV_2_90a 0x4f54290a
#define DWC2_CORE_REV_2_91a 0x4f54291a
#define DWC2_CORE_REV_2_92a 0x4f54292a
#define DWC2_CORE_REV_2_94a 0x4f54294a
#define DWC2_CORE_REV_3_00a 0x4f54300a
#define DWC2_CORE_REV_3_10a 0x4f54310a
#define DWC2_CORE_REV_4_00a 0x4f54400a
#define DWC2_FS_IOT_REV_1_00a 0x5531100a
#define DWC2_HS_IOT_REV_1_00a 0x5532100a
/* DWC OTG HW Core ID */
#define DWC2_OTG_ID 0x4f540000
#define DWC2_FS_IOT_ID 0x55310000
#define DWC2_HS_IOT_ID 0x55320000
struct dwc2_hsotg {
uint8_t *aligned_buffer;
uint8_t *status_buffer;
u8 in_data_toggle[MAX_DEVICE][MAX_EPS_CHANNELS];
u8 out_data_toggle[MAX_DEVICE][MAX_EPS_CHANNELS];
struct dwc2_core_regs *regs;
u32 reg_base;
struct dwc2_hw_params hw_params;
int root_hub_devnum;
/*from Linux start*/
u8 otg_cap;
#define DWC2_CAP_PARAM_HNP_SRP_CAPABLE 0
#define DWC2_CAP_PARAM_SRP_ONLY_CAPABLE 1
#define DWC2_CAP_PARAM_NO_HNP_SRP_CAPABLE 2
u8 phy_type;
#define DWC2_PHY_TYPE_PARAM_FS 0
#define DWC2_PHY_TYPE_PARAM_UTMI 1
#define DWC2_PHY_TYPE_PARAM_ULPI 2
u8 speed;
#define DWC2_SPEED_PARAM_HIGH 0
#define DWC2_SPEED_PARAM_FULL 1
#define DWC2_SPEED_PARAM_LOW 2
u8 phy_utmi_width;
bool phy_ulpi_ddr;
bool phy_ulpi_ext_vbus;
bool enable_dynamic_fifo;
bool en_multiple_tx_fifo;
bool i2c_enable;
bool acg_enable;
bool ulpi_fs_ls;
bool ts_dline;
bool reload_ctl;
bool uframe_sched;
bool external_id_pin_ctl;
int power_down;
#define DWC2_POWER_DOWN_PARAM_NONE 0
#define DWC2_POWER_DOWN_PARAM_PARTIAL 1
#define DWC2_POWER_DOWN_PARAM_HIBERNATION 2
bool lpm;
bool lpm_clock_gating;
bool besl;
bool hird_threshold_en;
u8 hird_threshold;
bool activate_stm_fs_transceiver;
bool ipg_isoc_en;
u16 max_packet_count;
u32 max_transfer_size;
u32 ahbcfg;
/* Host parameters */
bool host_dma;
bool dma_desc_enable;
bool dma_desc_fs_enable;
bool host_support_fs_ls_low_power;
bool host_ls_low_power_phy_clk;
bool oc_disable;
u8 host_channels;
u16 host_rx_fifo_size;
u16 host_nperio_tx_fifo_size;
u16 host_perio_tx_fifo_size;
/* Gadget parameters */
bool g_dma;
bool g_dma_desc;
u32 g_rx_fifo_size;
u32 g_np_tx_fifo_size;
u32 g_tx_fifo_size[MAX_EPS_CHANNELS];
bool change_speed_quirk;
/*from Linux end*/
/*
* The hnp/srp capability must be disabled if the platform
* does't support hnp/srp. Otherwise the force mode can't work.
*/
bool hnp_srp_disable;
};
/* device request (setup) */
struct devrequest {
__u8 requesttype;
__u8 request;
__le16 value;
__le16 index;
__le16 length;
} __attribute__ ((packed));
/* Interface */
struct usb_interface {
struct usb_interface_descriptor desc;
__u8 no_of_ep;
__u8 num_altsetting;
__u8 act_altsetting;
struct usb_endpoint_descriptor ep_desc[USB_MAXENDPOINTS];
/*
* Super Speed Device will have Super Speed Endpoint
* Companion Descriptor (section 9.6.7 of usb 3.0 spec)
* Revision 1.0 June 6th 2011
*/
struct usb_ss_ep_comp_descriptor ss_ep_comp_desc[USB_MAXENDPOINTS];
} __attribute__ ((packed));
/* Configuration information.. */
struct usb_config {
struct usb_config_descriptor desc;
__u8 no_of_if; /* number of interfaces */
struct usb_interface if_desc[USB_MAXINTERFACES];
} __attribute__ ((packed));
enum {
/* Maximum packet size; encoded as 0,1,2,3 = 8,16,32,64 */
PACKET_SIZE_8 = 0,
PACKET_SIZE_16 = 1,
PACKET_SIZE_32 = 2,
PACKET_SIZE_64 = 3,
};
struct usb_device {
int devnum; /* Device number on USB bus */
int speed; /* full/low/high */
char mf[32]; /* manufacturer */
char prod[32]; /* product */
char serial[32]; /* serial number */
/* Maximum packet size; one of: PACKET_SIZE_* */
int maxpacketsize;
/* one bit for each endpoint ([0] = IN, [1] = OUT) */
unsigned int toggle[2];
/* endpoint halts; one bit per endpoint # & direction;
* [0] = IN, [1] = OUT
*/
unsigned int halted[2];
int epmaxpacketin[16]; /* INput endpoint specific maximums */
int epmaxpacketout[16]; /* OUTput endpoint specific maximums */
int configno; /* selected config number */
/* Device Descriptor */
struct usb_device_descriptor descriptor;
struct usb_config config; /* config descriptor */
int have_langid; /* whether string_langid is valid yet */
int string_langid; /* language ID for strings */
int (*irq_handle)(struct usb_device *dev);
unsigned long irq_status;
int irq_act_len; /* transferred bytes */
void *privptr;
/*
* Child devices - if this is a hub device
* Each instance needs its own set of data structures.
*/
unsigned long status;
unsigned long int_pending; /* 1 bit per ep, used by int_queue */
int transfer_len; /* transferred bytes */
int maxchild; /* Number of ports if hub */
int portnr; /* Port number, 1=first */
/* parent hub, or NULL if this is the root hub */
struct usb_device *parent;
struct usb_device *children[USB_MAXCHILDREN];
void *controller; /* hardware controller private data */
/* slot_id - for xHCI enabled devices */
unsigned int slot_id;
};
/* USB Command Block Wrapper */
typedef struct cbw_struct {
uint_8 DCBWSIGNATURE[4];
uint_8 DCBWTAG[4];
uint_8 DCBWDATALENGTH[4];
uchar BMCBWFLAGS;
/* 4 MSBs bits reserved */
uchar BCBWCBLUN;
/* 3 MSB reserved */
uchar BCBWCBLENGTH;
uchar CBWCB[16];
} CBW_STRUCT, _PTR_ CBW_STRUCT_PTR;
/* UFI Typical Command Block Wrapper for Extended commands */
typedef struct _UFI_CBWCB_EXTENDED
{
uint_8 BUFIOPCODE; /* 0 */
uint_8 BUFILUN; /* 1 */
uint_8 BUFILOGICALBLOCKADDRESS[4]; /* 2,3,4,5 */
uint_8 BLENGTH[4]; /* 6,7,8,9 length of the data block */
uint_8 RESERVED10; /* 10 Reserved */
uint_8 RESERVED11; /* 11 Reserved */
} UFI_CBWCB_EXTENDED, _PTR_ UFI_CBWCB_EXTENDED_STRUCT_PTR;
struct usb_mass_data {
struct usb_device *pusb_dev; /* this usb_device */
unsigned char ifnum; /* interface number */
unsigned char ep_in; /* in endpoint */
unsigned char ep_out; /* out ....... */
unsigned char ep_int; /* interrupt . */
unsigned char irqinterval; /* Intervall for IRQ Pipe */
};
enum {
MASS_WAIT_NEW_CMD = 0,
MASS_WAIT_CMD_DONE,
MASS_WAIT_DATA_DONE,
MASS_WAIT_STATUS_DONE,
} usb_mass_isr_state_e;
/* Normal architectures just use readl/write */
static inline u32 dwc2_readl(struct dwc2_hsotg *hsotg, u32 offset)
{
u32 val;
val = readl((long long)(hsotg->reg_base + offset));
return val;
}
static inline void dwc2_writel(struct dwc2_hsotg *hsotg, u32 value, u32 offset)
{
writel(value, (long long)(hsotg->reg_base + offset));
}
/*
* The following functions support initialization of the core driver component
* and the DWC_otg controller
*/
int dwc2_core_reset(struct dwc2_hsotg *hsotg);
/*
* Common core Functions.
* The following functions support managing the DWC_otg controller in either
* device or host mode.
*/
void dwc2_flush_tx_fifo(struct dwc2_hsotg *hsotg, const int num);
void dwc2_flush_rx_fifo(struct dwc2_hsotg *hsotg);
/* Common polling functions */
int dwc2_hsotg_wait_bit_set(struct dwc2_hsotg *hs_otg, u32 reg, u32 bit,
u32 timeout);
int dwc2_hsotg_wait_bit_clear(struct dwc2_hsotg *hs_otg, u32 reg, u32 bit,
u32 timeout);
#if defined(CONFIG_USB_MUSB_HOST) || defined(CONFIG_DM_USB)
int usb_reset_root_port(struct usb_device *dev);
#else
#define usb_reset_root_port(dev)
#endif
extern int g_mass_blen;
extern int g_mass_blocking;
extern int g_mass_storage_timeout;
extern struct usb_device *pdev_usb;
extern void free(void *ptr);
extern void dbg_dump_buffer(unsigned char *b, int len);
extern int register_isr(void (*isr)(void), int irq_id);
extern void set_irq_enable(int irq_id);
extern void usb_mass_callback();
extern int dwc2_wait_device_detection();
extern void dwc2_init(struct dwc2_hsotg *hsotg);
extern int dwc2_hw_init(struct dwc2_hsotg *hsotg);
extern void dwc2_host_reset(struct dwc2_core_regs *regs);
extern int que_blk_msg(struct usb_device *dev, unsigned long pipe, void *buffer, int len);
extern void mydelay_us(int n); //From diag_USB.c
extern void dbg_dump_buffer(unsigned char *b, int len);
extern void dbg_dump_buffer_long(unsigned long *b, int len);
extern void dbg_out(char *s);
extern void dbg_outhex(int n);
extern void dbg_outb(unsigned char n);
extern void dbg_outw(unsigned int n);
extern void dbg_disp(char *s);
extern void usb_reset();
extern int usb_host_init();
extern int usb_mass_start();
extern int usb_storage_read(unsigned char *buff, int lba, int blk_count);
extern int usb_storage_write(unsigned char *buff, int lba, int blk_count);
extern int urb_control(struct usb_device *dev, unsigned int pipe,
unsigned char request, unsigned char requesttype,
unsigned short value, unsigned short index,
void *data, unsigned short size, int timeout);
extern int urb_bulk(struct usb_device *dev, unsigned int pipe,
void *data, int len, int *actual_length, int timeout);
extern int usb_maxpacket(struct usb_device *dev, unsigned long pipe);
extern int usb_get_configuration_no(struct usb_device *dev,
unsigned char *buffer, int length);
extern int usb_get_configuration_len(struct usb_device *dev);
extern int usb_descriptor_u2c(struct usb_device *dev, int index, char *buf, size_t size);
extern int set_interface(struct usb_device *dev, int interface, int alternate);
extern int snd_blk_msg(struct usb_device *dev, unsigned long pipe,
void *buffer, int transfer_len);
extern int snd_ctl_msg(struct usb_device *dev, unsigned long pipe, void *buffer,
int transfer_len, struct devrequest *setup);
extern int usb2_phy_status(int long_dump);
extern int usb_phy_init(void);
extern void * USB_memalloc(unsigned int n);
extern void USB_memfree(void * aligned_ptr);
extern void mydelay_us(int n);
extern void mydelay_ms(int n);
extern int usb_host_init();
extern int usb_mass_start();
extern int usb_storage_read(unsigned char *buff, int lba, int blk_count);
extern int usb_storage_write(unsigned char *buff, int lba, int blk_count);
extern int usb_storage_prevent_medium_removal();
extern void usb2_set_dbg_mode(unsigned int mode);
extern void dbg_display();
extern void dbg_out( char *s );
extern void dbg_outdw(unsigned int n);
extern void dbg_outw(unsigned int n);
extern void dbg_outb(unsigned char n);
extern void dbg_dump_buffer(unsigned char *b, int len);
extern void dbg_dump_buffer_long(unsigned long *b, int len);
extern void dbg_disp(char *s);
extern int usb_hub_probe(struct usb_device *dev, int ifnum);
extern void usb_find_usb2_hub_address_port(struct usb_device *udev,
uint8_t *hub_address, uint8_t *hub_port);
int usb_device_data_init(struct usb_device **devp);
typedef struct usb_dwc2_ops {
int (*packet_msg)(struct dwc2_hsotg *hsotg, struct usb_device *dev,
unsigned long pipe, u8 *pid, int in, void *buffer, int len);
int (*packet_snd)(struct dwc2_hc_regs *hc_regs, void *aligned_buffer,
u8 *pid, int in, void *buffer, int num_packets,
int xfer_len, int *actual_len, int odd_frame);
int (*ctl)(struct dwc2_hsotg *hsotg, struct usb_device *dev,
unsigned long pipe, void *buffer, int len, struct devrequest *setup);
int (*blk)(struct dwc2_hsotg *hsotg, struct usb_device *dev,
unsigned long pipe, void *buffer, int len);
} hcd_dwc2_ops_t;
/* routines */
int usb_init(void); /* initialize the USB Controller */
int usb_stop(void); /* stop the USB Controller */
int usb_get_port_status(struct usb_device *dev, int port, void *data);
/*************************************************************************
* Hub Stuff
*/
struct usb_port_status {
unsigned short wPortStatus;
unsigned short wPortChange;
} __attribute__ ((packed));
struct usb_hub_status {
unsigned short wHubStatus;
unsigned short wHubChange;
} __attribute__ ((packed));
/*
* Hub Device descriptor
* USB Hub class device protocols
*/
#define USB_HUB_PR_FS 0 /* Full speed hub */
#define USB_HUB_PR_HS_NO_TT 0 /* Hi-speed hub without TT */
#define USB_HUB_PR_HS_SINGLE_TT 1 /* Hi-speed hub with single TT */
#define USB_HUB_PR_HS_MULTI_TT 2 /* Hi-speed hub with multiple TT */
#define USB_HUB_PR_SS 3 /* Super speed hub */
/* Transaction Translator Think Times, in bits */
#define HUB_TTTT_8_BITS 0x00
#define HUB_TTTT_16_BITS 0x20
#define HUB_TTTT_24_BITS 0x40
#define HUB_TTTT_32_BITS 0x60
/* Hub descriptor */
struct usb_hub_descriptor {
unsigned char bLength;
unsigned char bDescriptorType;
unsigned char bNbrPorts;
unsigned short wHubCharacteristics;
unsigned char bPwrOn2PwrGood;
unsigned char bHubContrCurrent;
/* 2.0 and 3.0 hubs differ here */
union {
struct {
/* add 1 bit for hub status change; round to bytes */
__u8 DeviceRemovable[(USB_MAXCHILDREN + 1 + 7) / 8];
__u8 PortPowerCtrlMask[(USB_MAXCHILDREN + 1 + 7) / 8];
} __attribute__ ((packed)) hs;
struct {
__u8 bHubHdrDecLat;
__le16 wHubDelay;
__le16 DeviceRemovable;
} __attribute__ ((packed)) ss;
} u;
} __attribute__ ((packed));
/*
* As of USB 2.0, full/low speed devices are segregated into trees.
* One type grows from USB 1.1 host controllers (OHCI, UHCI etc).
* The other type grows from high speed hubs when they connect to
* full/low speed devices using "Transaction Translators" (TTs).
*/
struct usb_tt {
bool multi; /* true means one TT per port */
unsigned think_time; /* think time in ns */
};
struct usb_hub_device {
struct usb_device *pusb_dev;
struct usb_hub_descriptor desc;
ulong connect_timeout; /* Device connection timeout in ms */
ulong query_delay; /* Device query delay in ms */
int overcurrent_count[USB_MAXCHILDREN]; /* Over-current counter */
int hub_depth; /* USB 3.0 hub depth */
struct usb_tt tt; /* Transaction Translator */
};
bool usb_device_has_child_on_port(struct usb_device *parent, int port);
void usb_hub_reset(void);
int usb_new_device(struct usb_device *dev);
void usb_free_device(struct usb_device *controller);
#define USB_DT_HID (USB_TYPE_CLASS | 0x01)
#define USB_DT_REPORT (USB_TYPE_CLASS | 0x02)
#define USB_DT_PHYSICAL (USB_TYPE_CLASS | 0x03)
#define USB_DT_HUB (USB_TYPE_CLASS | 0x09)
#define USB_DT_SS_HUB (USB_TYPE_CLASS | 0x0a)
/*************************************************************************
* Hub defines
*/
/*
* Hub request types
*/
#define USB_RT_HUB (USB_TYPE_CLASS | USB_RECIP_DEVICE)
#define USB_RT_PORT (USB_TYPE_CLASS | USB_RECIP_OTHER)
/*
* Hub Class feature numbers
*/
#define C_HUB_LOCAL_POWER 0
#define C_HUB_OVER_CURRENT 1
/*
* Port feature numbers
*/
#define USB_PORT_FEAT_CONNECTION 0
#define USB_PORT_FEAT_ENABLE 1
#define USB_PORT_FEAT_SUSPEND 2
#define USB_PORT_FEAT_OVER_CURRENT 3
#define USB_PORT_FEAT_RESET 4
#define USB_PORT_FEAT_POWER 8
#define USB_PORT_FEAT_LOWSPEED 9
#define USB_PORT_FEAT_HIGHSPEED 10
#define USB_PORT_FEAT_C_CONNECTION 16
#define USB_PORT_FEAT_C_ENABLE 17
#define USB_PORT_FEAT_C_SUSPEND 18
#define USB_PORT_FEAT_C_OVER_CURRENT 19
#define USB_PORT_FEAT_C_RESET 20
#define USB_PORT_FEAT_TEST 21
/*
* Changes to Port feature numbers for Super speed,
* from USB 3.0 spec Table 10-8
*/
#define USB_SS_PORT_FEAT_U1_TIMEOUT 23
#define USB_SS_PORT_FEAT_U2_TIMEOUT 24
#define USB_SS_PORT_FEAT_C_LINK_STATE 25
#define USB_SS_PORT_FEAT_C_CONFIG_ERROR 26
#define USB_SS_PORT_FEAT_BH_RESET 28
#define USB_SS_PORT_FEAT_C_BH_RESET 29
/* wPortStatus bits */
#define USB_PORT_STAT_CONNECTION 0x0001
#define USB_PORT_STAT_ENABLE 0x0002
#define USB_PORT_STAT_SUSPEND 0x0004
#define USB_PORT_STAT_OVERCURRENT 0x0008
#define USB_PORT_STAT_RESET 0x0010
#define USB_PORT_STAT_POWER 0x0100
#define USB_PORT_STAT_LOW_SPEED 0x0200
#define USB_PORT_STAT_HIGH_SPEED 0x0400 /* support for EHCI */
#define USB_PORT_STAT_SUPER_SPEED 0x0600 /* faking support to XHCI */
#define USB_PORT_STAT_SPEED_MASK \
(USB_PORT_STAT_LOW_SPEED | USB_PORT_STAT_HIGH_SPEED)
/*
* Changes to wPortStatus bit field in USB 3.0
* See USB 3.0 spec Table 10-10
*/
#define USB_SS_PORT_STAT_LINK_STATE 0x01e0
#define USB_SS_PORT_STAT_POWER 0x0200
#define USB_SS_PORT_STAT_SPEED 0x1c00
#define USB_SS_PORT_STAT_SPEED_5GBPS 0x0000
/* Bits that are the same from USB 2.0 */
#define USB_SS_PORT_STAT_MASK (USB_PORT_STAT_CONNECTION | \
USB_PORT_STAT_ENABLE | \
USB_PORT_STAT_OVERCURRENT | \
USB_PORT_STAT_RESET)
/* wPortChange bits */
#define USB_PORT_STAT_C_CONNECTION 0x0001
#define USB_PORT_STAT_C_ENABLE 0x0002
#define USB_PORT_STAT_C_SUSPEND 0x0004
#define USB_PORT_STAT_C_OVERCURRENT 0x0008
#define USB_PORT_STAT_C_RESET 0x0010
/*
* Changes to wPortChange bit fields in USB 3.0
* See USB 3.0 spec Table 10-12
*/
#define USB_SS_PORT_STAT_C_BH_RESET 0x0020
#define USB_SS_PORT_STAT_C_LINK_STATE 0x0040
#define USB_SS_PORT_STAT_C_CONFIG_ERROR 0x0080
/* wHubCharacteristics (masks) */
#define HUB_CHAR_LPSM 0x0003
#define HUB_CHAR_COMPOUND 0x0004
#define HUB_CHAR_OCPM 0x0018
#define HUB_CHAR_TTTT 0x0060 /* TT Think Time mask */
/*
* Hub Status & Hub Change bit masks
*/
#define HUB_STATUS_LOCAL_POWER 0x0001
#define HUB_STATUS_OVERCURRENT 0x0002
#define HUB_CHANGE_LOCAL_POWER 0x0001
#define HUB_CHANGE_OVERCURRENT 0x0002
/* Mask for wIndex in get/set port feature */
#define USB_HUB_PORT_MASK 0xf
/* Hub class request codes */
#define USB_REQ_SET_HUB_DEPTH 0x0c
#endif /* __DWC2_CORE_H__ */