Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 16817354 authored by Jack Pham's avatar Jack Pham
Browse files

usb: dwc3: Add DWC3 MSM driver



This change adds the driver for the USB controller on QTI MSM
devices.  This is a snapshot of the driver from msm-4.19 as of
commit 104eef6e1fe8 ("platform: msm: Remove unused local count
variable").

In addition to the msm-4.19 version, this change includes several
fixups to address the following:

  - Building dwc3-msm as a module. It is easiest to just merge
    dbm.c into dwc3-msm.c.
  - Coccinelle warnings, such as assigning 0/1 to a boolean and
    missing newlines from log strings.
  - Conversion of defunct msm_bus API to the interconnect bus
    scaling API.
  - Remove dead host controller handling as it depends on a
    USB_BUS_DIED notification added to usbcore on downstream and
    has not yet been mainlined on this kernel. We will either have
    to bring in the atomic notifier or switch to listening to the
    "ERROR=DEAD" uevent and take action from userspace.
  - Remove extcon blocking notifier and MED_HIGH_CURRENT.
  - Remove usage of PM_QOS_REQ_AFFINE_IRQ as PM QoS support for
    specifying IRQ/CPU affinity is not supported upstream. Just
    request a QoS level for all cores.
  - Endpoints' ep_type EP_TYPE_GSI is now reflected in dep->gsi
  - dwc3_stop_active_transfer() takes a dep directly and added
    an additional parameter to skip IOC
  - Remove RESTART_USB_SESSION notification as the usb_gadget_ops
    restart_session is not supported in upstream
  - dwc3_request->started replaced by DWC3_REQUEST_STATUS_STARTED
  - Switch USB_DR_MODE_DRD enum back to USB_DR_MODE_OTG
  - Directly write GUSB3PIPECTL_SUSPHY and DEVTEN registers instead
    of needing APIs from core
  - Remove clk_set_flags. These aren't needed now.
  - Remove FLOAT charger handling.

Change-Id: I9a13cb5bae2f5c1e98906d1cb52134c2dea0bc80
Signed-off-by: default avatarJack Pham <jackp@codeaurora.org>
parent 669a7f8d
Loading
Loading
Loading
Loading
+9 −0
Original line number Diff line number Diff line
@@ -137,4 +137,13 @@ config USB_DWC3_QCOM
	  for peripheral mode support.
	  Say 'Y' or 'M' if you have one such device.

config USB_DWC3_MSM
	tristate "QTI MSM Platforms"
	depends on ARCH_QCOM || COMPILE_TEST
	help
	  Applicable to QTI MSM Platforms with DesignWare Core
	  USB3 IP.
	  Driver supports host, device and dual-role modes of operation.
	  Say 'Y' or 'M' if you have one such device.

endif
+2 −0
Original line number Diff line number Diff line
# SPDX-License-Identifier: GPL-2.0
# define_trace.h needs to know how to find our header
CFLAGS_trace.o				:= -I$(src)
CFLAGS_dwc3-msm.o                       := -I$(srctree)/drivers/usb/host

obj-$(CONFIG_USB_DWC3)			+= dwc3.o

@@ -51,3 +52,4 @@ obj-$(CONFIG_USB_DWC3_MESON_G12A) += dwc3-meson-g12a.o
obj-$(CONFIG_USB_DWC3_OF_SIMPLE)	+= dwc3-of-simple.o
obj-$(CONFIG_USB_DWC3_ST)		+= dwc3-st.o
obj-$(CONFIG_USB_DWC3_QCOM)		+= dwc3-qcom.o
obj-$(CONFIG_USB_DWC3_MSM)		+= dwc3-msm.o
+4869 −0

File added.

Preview size limit exceeded, changes collapsed.

+144 −0
Original line number Diff line number Diff line
/* SPDX-License-Identifier: GPL-2.0-only */
/*
 * Copyright (c) 2019, The Linux Foundation. All rights reserved.
 */

#ifndef __LINUX_USB_DWC3_MSM_H
#define __LINUX_USB_DWC3_MSM_H

/* used for struct usb_phy flags */
#define ENABLE_DP_MANUAL_PULLUP		BIT(0)
#define ENABLE_SECONDARY_PHY		BIT(1)
#define PHY_HOST_MODE			BIT(2)
#define PHY_CHARGER_CONNECTED		BIT(3)
#define PHY_VBUS_VALID_OVERRIDE		BIT(4)
#define DEVICE_IN_SS_MODE		BIT(5)
#define PHY_LANE_A			BIT(6)
#define PHY_LANE_B			BIT(7)
#define PHY_HSFS_MODE			BIT(8)
#define PHY_LS_MODE			BIT(9)
#define PHY_USB_DP_CONCURRENT_MODE	BIT(10)

/*
 * The following are bit fields describing the USB BAM options.
 * These bit fields are set by function drivers that wish to queue
 * usb_requests with sps/bam parameters.
 */
#define MSM_PIPE_ID_MASK		(0x1F)
#define MSM_TX_PIPE_ID_OFS		(16)
#define MSM_SPS_MODE			BIT(5)
#define MSM_IS_FINITE_TRANSFER		BIT(6)
#define MSM_PRODUCER			BIT(7)
#define MSM_DISABLE_WB			BIT(8)
#define MSM_ETD_IOC			BIT(9)
#define MSM_INTERNAL_MEM		BIT(10)
#define MSM_VENDOR_ID			BIT(16)

/* Operations codes for GSI enabled EPs */
enum gsi_ep_op {
	GSI_EP_OP_CONFIG = 0,
	GSI_EP_OP_STARTXFER,
	GSI_EP_OP_STORE_DBL_INFO,
	GSI_EP_OP_ENABLE_GSI,
	GSI_EP_OP_UPDATEXFER,
	GSI_EP_OP_RING_DB,
	GSI_EP_OP_ENDXFER,
	GSI_EP_OP_GET_CH_INFO,
	GSI_EP_OP_GET_XFER_IDX,
	GSI_EP_OP_PREPARE_TRBS,
	GSI_EP_OP_FREE_TRBS,
	GSI_EP_OP_SET_CLR_BLOCK_DBL,
	GSI_EP_OP_CHECK_FOR_SUSPEND,
	GSI_EP_OP_DISABLE,
};

/*
 * @buf_base_addr: Base pointer to buffer allocated for each GSI enabled EP.
 *	TRBs point to buffers that are split from this pool. The size of the
 *	buffer is num_bufs times buf_len. num_bufs and buf_len are determined
	based on desired performance and aggregation size.
 * @dma: DMA address corresponding to buf_base_addr.
 * @num_bufs: Number of buffers associated with the GSI enabled EP. This
 *	corresponds to the number of non-zlp TRBs allocated for the EP.
 *	The value is determined based on desired performance for the EP.
 * @buf_len: Size of each individual buffer is determined based on aggregation
 *	negotiated as per the protocol. In case of no aggregation supported by
 *	the protocol, we use default values.
 * @db_reg_phs_addr_lsb: IPA channel doorbell register's physical address LSB
 * @mapped_db_reg_phs_addr_lsb: doorbell LSB IOVA address mapped with IOMMU
 * @db_reg_phs_addr_msb: IPA channel doorbell register's physical address MSB
 * @ep_intr_num: Interrupter number for EP.
 */
struct usb_gsi_request {
	void *buf_base_addr;
	dma_addr_t dma;
	size_t num_bufs;
	size_t buf_len;
	u32 db_reg_phs_addr_lsb;
	dma_addr_t mapped_db_reg_phs_addr_lsb;
	u32 db_reg_phs_addr_msb;
	u8 ep_intr_num;
	struct sg_table sgt_trb_xfer_ring;
	struct sg_table sgt_data_buff;
};

/*
 * @last_trb_addr: Address (LSB - based on alignment restrictions) of
 *	last TRB in queue. Used to identify rollover case.
 * @const_buffer_size: TRB buffer size in KB (similar to IPA aggregation
 *	configuration). Must be aligned to Max USB Packet Size.
 *	Should be 1 <= const_buffer_size <= 31.
 * @depcmd_low_addr: Used by GSI hardware to write "Update Transfer" cmd
 * @depcmd_hi_addr: Used to write "Update Transfer" command.
 * @gevntcount_low_addr: GEVNCOUNT low address for GSI hardware to read and
 *	clear processed events.
 * @gevntcount_hi_addr:	GEVNCOUNT high address.
 * @xfer_ring_len: length of transfer ring in bytes (must be integral
 *	multiple of TRB size - 16B for xDCI).
 * @xfer_ring_base_addr: physical base address of transfer ring. Address must
 *	be aligned to xfer_ring_len rounded to power of two.
 * @ch_req: Used to pass request specific info for certain operations on GSI EP
 */
struct gsi_channel_info {
	u16 last_trb_addr;
	u8 const_buffer_size;
	u32 depcmd_low_addr;
	u8 depcmd_hi_addr;
	u32 gevntcount_low_addr;
	u8 gevntcount_hi_addr;
	u16 xfer_ring_len;
	u64 xfer_ring_base_addr;
	struct usb_gsi_request *ch_req;
};

#if IS_ENABLED(CONFIG_USB_DWC3_MSM)
int usb_gsi_ep_op(struct usb_ep *ep, void *op_data, enum gsi_ep_op op);
int msm_ep_config(struct usb_ep *ep, struct usb_request *request, u32 bam_opts);
int msm_ep_unconfig(struct usb_ep *ep);
void dwc3_tx_fifo_resize_request(struct usb_ep *ep, bool qdss_enable);
int msm_data_fifo_config(struct usb_ep *ep, unsigned long addr, u32 size,
	u8 dst_pipe_idx);
bool msm_dwc3_reset_ep_after_lpm(struct usb_gadget *gadget);
int msm_dwc3_reset_dbm_ep(struct usb_ep *ep);
#else
static inline int usb_gsi_ep_op(struct usb_ep *ep, void *op_data,
		enum gsi_ep_op op)
{ return 0; }
static inline int msm_data_fifo_config(struct usb_ep *ep, unsigned long addr,
	u32 size, u8 dst_pipe_idx)
{ return -ENODEV; }
static inline int msm_ep_config(struct usb_ep *ep, struct usb_request *request,
		u32 bam_opts)
{ return -ENODEV; }
static inline int msm_ep_unconfig(struct usb_ep *ep)
{ return -ENODEV; }
static inline void dwc3_tx_fifo_resize_request(struct usb_ep *ep,
	bool qdss_enable)
{ }
static inline bool msm_dwc3_reset_ep_after_lpm(struct usb_gadget *gadget)
{ return false; }
static inline int msm_dwc3_reset_dbm_ep(struct usb_ep *ep)
{ return -ENODEV; }
#endif

#endif /* __LINUX_USB_DWC3_MSM_H */