summaryrefslogtreecommitdiff
path: root/include/linux/usb
diff options
context:
space:
mode:
Diffstat (limited to 'include/linux/usb')
-rw-r--r--include/linux/usb/composite.h24
-rw-r--r--include/linux/usb/f_mtp.h30
-rw-r--r--include/linux/usb/gadget.h285
-rw-r--r--include/linux/usb/hcd.h21
-rw-r--r--include/linux/usb/msm_hsusb.h146
-rw-r--r--include/linux/usb/phy.h13
-rw-r--r--include/linux/usb/usb_qdss.h94
-rw-r--r--include/linux/usb/usbdiag.h85
-rw-r--r--include/linux/usb/usbpd.h159
9 files changed, 852 insertions, 5 deletions
diff --git a/include/linux/usb/composite.h b/include/linux/usb/composite.h
index 15d7c311e86e..bc5637ab01df 100644
--- a/include/linux/usb/composite.h
+++ b/include/linux/usb/composite.h
@@ -41,6 +41,10 @@
#include <linux/log2.h>
#include <linux/configfs.h>
+/* FUNCTION_SUSPEND: suspend options from usb 3.0 spec Table 9-7 */
+#define FUNC_SUSPEND_OPT_SUSP_MASK BIT(0)
+#define FUNC_SUSPEND_OPT_RW_EN_MASK BIT(1)
+
/*
* USB function drivers should return USB_GADGET_DELAYED_STATUS if they
* wish to delay the data/status stages of the control transfer till they
@@ -154,7 +158,14 @@ struct usb_os_desc_table {
* @get_status: Returns function status as a reply to
* GetStatus() request when the recipient is Interface.
* @func_suspend: callback to be called when
- * SetFeature(FUNCTION_SUSPEND) is reseived
+ * SetFeature(FUNCTION_SUSPEND) is received
+ * @func_is_suspended: Tells whether the function is currently in
+ * Function Suspend state (used in Super Speed mode only).
+ * @func_wakeup_allowed: Tells whether Function Remote Wakeup has been allowed
+ * by the USB host (used in Super Speed mode only).
+ * @func_wakeup_pending: Marks that the function has issued a Function Wakeup
+ * while the USB bus was suspended and therefore a Function Wakeup
+ * notification needs to be sent once the USB bus is resumed.
*
* A single USB function uses one or more interfaces, and should in most
* cases support operation at both full and high speeds. Each function is
@@ -182,6 +193,7 @@ struct usb_os_desc_table {
struct usb_function {
const char *name;
+ int intf_id;
struct usb_gadget_strings **strings;
struct usb_descriptor_header **fs_descriptors;
struct usb_descriptor_header **hs_descriptors;
@@ -223,6 +235,9 @@ struct usb_function {
int (*get_status)(struct usb_function *);
int (*func_suspend)(struct usb_function *,
u8 suspend_opt);
+ unsigned func_is_suspended:1;
+ unsigned func_wakeup_allowed:1;
+ unsigned func_wakeup_pending:1;
/* private: */
/* internals */
struct list_head list;
@@ -238,6 +253,9 @@ int usb_function_deactivate(struct usb_function *);
int usb_function_activate(struct usb_function *);
int usb_interface_id(struct usb_configuration *, struct usb_function *);
+int usb_func_wakeup(struct usb_function *func);
+
+int usb_get_func_interface_id(struct usb_function *func);
int config_ep_by_speed(struct usb_gadget *g, struct usb_function *f,
struct usb_ep *_ep);
@@ -318,6 +336,10 @@ struct usb_configuration {
unsigned highspeed:1;
unsigned fullspeed:1;
struct usb_function *interface[MAX_CONFIG_INTERFACES];
+
+ /* number of in and out eps used in this configuration */
+ int num_ineps_used;
+ int num_outeps_used;
};
int usb_add_config(struct usb_composite_dev *,
diff --git a/include/linux/usb/f_mtp.h b/include/linux/usb/f_mtp.h
index 4e8417791bea..8def1431f03e 100644
--- a/include/linux/usb/f_mtp.h
+++ b/include/linux/usb/f_mtp.h
@@ -19,5 +19,35 @@
#define __LINUX_USB_F_MTP_H
#include <uapi/linux/usb/f_mtp.h>
+#include <linux/ioctl.h>
+#ifdef CONFIG_COMPAT
+#include <linux/compat.h>
+#endif
+#ifdef __KERNEL__
+
+#ifdef CONFIG_COMPAT
+struct __compat_mtp_file_range {
+ compat_int_t fd;
+ compat_loff_t offset;
+ int64_t length;
+ uint16_t command;
+ uint32_t transaction_id;
+};
+
+struct __compat_mtp_event {
+ compat_size_t length;
+ compat_caddr_t data;
+};
+
+#define COMPAT_MTP_SEND_FILE _IOW('M', 0, \
+ struct __compat_mtp_file_range)
+#define COMPAT_MTP_RECEIVE_FILE _IOW('M', 1, \
+ struct __compat_mtp_file_range)
+#define COMPAT_MTP_SEND_EVENT _IOW('M', 3, \
+ struct __compat_mtp_event)
+#define COMPAT_MTP_SEND_FILE_WITH_HEADER _IOW('M', 4, \
+ struct __compat_mtp_file_range)
+#endif
+#endif
#endif /* __LINUX_USB_F_MTP_H */
diff --git a/include/linux/usb/gadget.h b/include/linux/usb/gadget.h
index 3d583a10b926..143e556f141d 100644
--- a/include/linux/usb/gadget.h
+++ b/include/linux/usb/gadget.h
@@ -24,9 +24,82 @@
#include <linux/types.h>
#include <linux/workqueue.h>
#include <linux/usb/ch9.h>
+#include <linux/pm_runtime.h>
struct usb_ep;
+enum ep_type {
+ EP_TYPE_NORMAL = 0,
+ EP_TYPE_GSI,
+};
+
+/* 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_IN_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.
+ */
+struct usb_gsi_request {
+ void *buf_base_addr;
+ dma_addr_t dma;
+ size_t num_bufs;
+ size_t buf_len;
+};
+
+/*
+ * @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;
+};
+
/**
* struct usb_request - describes one i/o request
* @buf: Buffer used for data. Always provide this; some controllers
@@ -46,6 +119,11 @@ struct usb_ep;
* by adding a zero length packet as needed;
* @short_not_ok: When reading data, makes short packets be
* treated as errors (queue stops advancing till cleanup).
+ * @dma_pre_mapped: Tells the USB core driver whether this request should be
+ * DMA-mapped before it is queued to the USB HW. When set to true, it means
+ * that the request has already been mapped in advance and therefore the
+ * USB core driver does NOT need to do DMA-mapping when the request is
+ * queued to the USB HW.
* @complete: Function called when request completes, so this request and
* its buffer may be re-used. The function will always be called with
* interrupts disabled, and it must not sleep.
@@ -69,6 +147,7 @@ struct usb_ep;
* Note that for writes (IN transfers) some data bytes may still
* reside in a device-side FIFO when the request is reported as
* complete.
+ * @udc_priv: Vendor private data in usage by the UDC.
*
* These are allocated/freed through the endpoint they're used with. The
* hardware's driver can add extra per-request data to the memory it returns,
@@ -101,6 +180,7 @@ struct usb_request {
unsigned no_interrupt:1;
unsigned zero:1;
unsigned short_not_ok:1;
+ unsigned dma_pre_mapped:1;
void (*complete)(struct usb_ep *ep,
struct usb_request *req);
@@ -109,6 +189,7 @@ struct usb_request {
int status;
unsigned actual;
+ unsigned udc_priv;
};
/*-------------------------------------------------------------------------*/
@@ -138,6 +219,8 @@ struct usb_ep_ops {
int (*fifo_status) (struct usb_ep *ep);
void (*fifo_flush) (struct usb_ep *ep);
+ int (*gsi_ep_op)(struct usb_ep *ep, void *op_data,
+ enum gsi_ep_op op);
};
/**
@@ -201,6 +284,10 @@ struct usb_ep_caps {
* enabled and remains valid until the endpoint is disabled.
* @comp_desc: In case of SuperSpeed support, this is the endpoint companion
* descriptor that is used to configure the endpoint
+ * @ep_type: Used to specify type of EP eg. normal vs h/w accelerated.
+ * @ep_intr_num: Interrupter number for EP.
+ * @endless: In case where endless transfer is being initiated, this is set
+ * to disable usb event interrupt for few events.
*
* the bus controller driver lists all the general purpose endpoints in
* gadget->ep_list. the control endpoint (gadget->ep0) is not in that list,
@@ -224,6 +311,10 @@ struct usb_ep {
u8 address;
const struct usb_endpoint_descriptor *desc;
const struct usb_ss_ep_comp_descriptor *comp_desc;
+ enum ep_type ep_type;
+ u8 ep_num;
+ u8 ep_intr_num;
+ bool endless;
};
/*-------------------------------------------------------------------------*/
@@ -526,7 +617,20 @@ static inline void usb_ep_fifo_flush(struct usb_ep *ep)
ep->ops->fifo_flush(ep);
}
+/**
+ * usb_gsi_ep_op - performs operation on GSI accelerated EP based on EP op code
+ *
+ * Operations such as EP configuration, TRB allocation, StartXfer etc.
+ * See gsi_ep_op for more details.
+ */
+static inline int usb_gsi_ep_op(struct usb_ep *ep,
+ struct usb_gsi_request *req, enum gsi_ep_op op)
+{
+ if (ep->ops->gsi_ep_op)
+ return ep->ops->gsi_ep_op(ep, req, op);
+ return -EOPNOTSUPP;
+}
/*-------------------------------------------------------------------------*/
struct usb_dcd_config_params {
@@ -547,10 +651,12 @@ struct usb_udc;
struct usb_gadget_ops {
int (*get_frame)(struct usb_gadget *);
int (*wakeup)(struct usb_gadget *);
+ int (*func_wakeup)(struct usb_gadget *, int interface_id);
int (*set_selfpowered) (struct usb_gadget *, int is_selfpowered);
int (*vbus_session) (struct usb_gadget *, int is_active);
int (*vbus_draw) (struct usb_gadget *, unsigned mA);
int (*pullup) (struct usb_gadget *, int is_on);
+ int (*restart)(struct usb_gadget *);
int (*ioctl)(struct usb_gadget *,
unsigned code, unsigned long param);
void (*get_config_params)(struct usb_dcd_config_params *);
@@ -646,6 +752,7 @@ struct usb_gadget {
unsigned is_selfpowered:1;
unsigned deactivated:1;
unsigned connected:1;
+ bool remote_wakeup;
};
#define work_to_gadget(w) (container_of((w), struct usb_gadget, work))
@@ -774,6 +881,26 @@ static inline int usb_gadget_wakeup(struct usb_gadget *gadget)
}
/**
+ * usb_gadget_func_wakeup - send a function remote wakeup up notification
+ * to the host connected to this gadget
+ * @gadget: controller used to wake up the host
+ * @interface_id: the interface which triggered the remote wakeup event
+ *
+ * Returns zero on success. Otherwise, negative error code is returned.
+ */
+static inline int usb_gadget_func_wakeup(struct usb_gadget *gadget,
+ int interface_id)
+{
+ if (gadget->speed != USB_SPEED_SUPER)
+ return -EOPNOTSUPP;
+
+ if (!gadget->ops->func_wakeup)
+ return -EOPNOTSUPP;
+
+ return gadget->ops->func_wakeup(gadget, interface_id);
+}
+
+/**
* usb_gadget_set_selfpowered - sets the device selfpowered feature.
* @gadget:the device being declared as self-powered
*
@@ -929,6 +1056,20 @@ static inline int usb_gadget_disconnect(struct usb_gadget *gadget)
}
/**
+ * usb_gadget_restart - software-controlled reset of USB peripheral connection
+ * @gadget:the peripheral being reset
+ *
+ * Informs controller driver for Vbus LOW followed by Vbus HIGH notification.
+ * This performs full hardware reset and re-initialization.
+ */
+static inline int usb_gadget_restart(struct usb_gadget *gadget)
+{
+ if (!gadget->ops->restart)
+ return -EOPNOTSUPP;
+ return gadget->ops->restart(gadget);
+}
+
+/**
* usb_gadget_deactivate - deactivate function which is not ready to work
* @gadget: the peripheral being deactivated
*
@@ -987,6 +1128,129 @@ static inline int usb_gadget_activate(struct usb_gadget *gadget)
return 0;
}
+/**
+ * usb_gadget_autopm_get - increment PM-usage counter of usb gadget's parent
+ * device.
+ * @gadget: usb gadget whose parent device counter is incremented
+ *
+ * This routine should be called by function driver when it wants to use
+ * gadget's parent device and needs to guarantee that it is not suspended. In
+ * addition, the routine prevents subsequent autosuspends of gadget's parent
+ * device. However if the autoresume fails then the counter is re-decremented.
+ *
+ * This routine can run only in process context.
+ */
+static inline int usb_gadget_autopm_get(struct usb_gadget *gadget)
+{
+ int status = -ENODEV;
+
+ if (!gadget || !gadget->dev.parent)
+ return status;
+
+ status = pm_runtime_get_sync(gadget->dev.parent);
+ if (status < 0)
+ pm_runtime_put_sync(gadget->dev.parent);
+
+ if (status > 0)
+ status = 0;
+ return status;
+}
+
+/**
+ * usb_gadget_autopm_get_async - increment PM-usage counter of usb gadget's
+ * parent device.
+ * @gadget: usb gadget whose parent device counter is incremented
+ *
+ * This routine increments @gadget parent device PM usage counter and queue an
+ * autoresume request if the device is suspended. It does not autoresume device
+ * directly (it only queues a request). After a successful call, the device may
+ * not yet be resumed.
+ *
+ * This routine can run in atomic context.
+ */
+static inline int usb_gadget_autopm_get_async(struct usb_gadget *gadget)
+{
+ int status = -ENODEV;
+
+ if (!gadget || !gadget->dev.parent)
+ return status;
+
+ status = pm_runtime_get(gadget->dev.parent);
+ if (status < 0 && status != -EINPROGRESS)
+ pm_runtime_put_noidle(gadget->dev.parent);
+
+ if (status > 0 || status == -EINPROGRESS)
+ status = 0;
+ return status;
+}
+
+/**
+ * usb_gadget_autopm_get_noresume - increment PM-usage counter of usb gadget's
+ * parent device.
+ * @gadget: usb gadget whose parent device counter is incremented
+ *
+ * This routine increments PM-usage count of @gadget parent device but does not
+ * carry out an autoresume.
+ *
+ * This routine can run in atomic context.
+ */
+static inline void usb_gadget_autopm_get_noresume(struct usb_gadget *gadget)
+{
+ if (gadget && gadget->dev.parent)
+ pm_runtime_get_noresume(gadget->dev.parent);
+}
+
+/**
+ * usb_gadget_autopm_put - decrement PM-usage counter of usb gadget's parent
+ * device.
+ * @gadget: usb gadget whose parent device counter is decremented.
+ *
+ * This routine should be called by function driver when it is finished using
+ * @gadget parent device and wants to allow it to autosuspend. It decrements
+ * PM-usage counter of @gadget parent device, when the counter reaches 0, a
+ * delayed autosuspend request is attempted.
+ *
+ * This routine can run only in process context.
+ */
+static inline void usb_gadget_autopm_put(struct usb_gadget *gadget)
+{
+ if (gadget && gadget->dev.parent)
+ pm_runtime_put_sync(gadget->dev.parent);
+}
+
+/**
+ * usb_gadget_autopm_put_async - decrement PM-usage counter of usb gadget's
+ * parent device.
+ * @gadget: usb gadget whose parent device counter is decremented.
+ *
+ * This routine decrements PM-usage counter of @gadget parent device and
+ * schedules a delayed autosuspend request if the counter is <= 0.
+ *
+ * This routine can run in atomic context.
+ */
+static inline void usb_gadget_autopm_put_async(struct usb_gadget *gadget)
+{
+ if (gadget && gadget->dev.parent)
+ pm_runtime_put(gadget->dev.parent);
+}
+
+/**
+ * usb_gadget_autopm_put_no_suspend - decrement PM-usage counter of usb gadget
+'s
+ * parent device.
+ * @gadget: usb gadget whose parent device counter is decremented.
+ *
+ * This routine decrements PM-usage counter of @gadget parent device but does
+ * not carry out an autosuspend.
+ *
+ * This routine can run in atomic context.
+ */
+static inline void usb_gadget_autopm_put_no_suspend(struct usb_gadget *gadget)
+{
+ if (gadget && gadget->dev.parent)
+ pm_runtime_put_noidle(gadget->dev.parent);
+}
+
/*-------------------------------------------------------------------------*/
/**
@@ -1196,6 +1460,24 @@ int usb_otg_descriptor_init(struct usb_gadget *gadget,
struct usb_descriptor_header *otg_desc);
/*-------------------------------------------------------------------------*/
+/**
+ * usb_func_ep_queue - queues (submits) an I/O request to a function endpoint.
+ * This function is similar to the usb_ep_queue function, but in addition it
+ * also checks whether the function is in Super Speed USB Function Suspend
+ * state, and if so a Function Wake notification is sent to the host
+ * (USB 3.0 spec, section 9.2.5.2).
+ * @func: the function which issues the USB I/O request.
+ * @ep:the endpoint associated with the request
+ * @req:the request being submitted
+ * @gfp_flags: GFP_* flags to use in case the lower level driver couldn't
+ * pre-allocate all necessary memory with the request.
+ *
+ */
+int usb_func_ep_queue(struct usb_function *func, struct usb_ep *ep,
+ struct usb_request *req, gfp_t gfp_flags);
+
+/*-------------------------------------------------------------------------*/
+
/* utility to simplify map/unmap of usb_requests to/from DMA */
extern int usb_gadget_map_request(struct usb_gadget *gadget,
@@ -1259,5 +1541,8 @@ extern struct usb_ep *usb_ep_autoconfig_ss(struct usb_gadget *,
extern void usb_ep_autoconfig_release(struct usb_ep *);
extern void usb_ep_autoconfig_reset(struct usb_gadget *);
+extern struct usb_ep *usb_ep_autoconfig_by_name(struct usb_gadget *,
+ struct usb_endpoint_descriptor *,
+ const char *ep_name);
#endif /* __LINUX_USB_GADGET_H */
diff --git a/include/linux/usb/hcd.h b/include/linux/usb/hcd.h
index f89c24bd53a4..cef429cf3dce 100644
--- a/include/linux/usb/hcd.h
+++ b/include/linux/usb/hcd.h
@@ -396,6 +396,14 @@ struct hc_driver {
/* Call for power on/off the port if necessary */
int (*port_power)(struct usb_hcd *hcd, int portnum, bool enable);
+ int (*sec_event_ring_setup)(struct usb_hcd *hcd, unsigned intr_num);
+ int (*sec_event_ring_cleanup)(struct usb_hcd *hcd, unsigned intr_num);
+ dma_addr_t (*get_sec_event_ring_dma_addr)(struct usb_hcd *hcd,
+ unsigned intr_num);
+ dma_addr_t (*get_xfer_ring_dma_addr)(struct usb_hcd *hcd,
+ struct usb_device *udev, struct usb_host_endpoint *ep);
+ dma_addr_t (*get_dcba_dma_addr)(struct usb_hcd *hcd,
+ struct usb_device *udev);
};
static inline int hcd_giveback_urb_in_bh(struct usb_hcd *hcd)
@@ -434,6 +442,17 @@ extern int usb_hcd_alloc_bandwidth(struct usb_device *udev,
struct usb_host_interface *old_alt,
struct usb_host_interface *new_alt);
extern int usb_hcd_get_frame_number(struct usb_device *udev);
+extern int usb_hcd_sec_event_ring_setup(struct usb_device *udev,
+ unsigned intr_num);
+extern int usb_hcd_sec_event_ring_cleanup(struct usb_device *udev,
+ unsigned intr_num);
+extern dma_addr_t
+usb_hcd_get_sec_event_ring_dma_addr(struct usb_device *udev,
+ unsigned intr_num);
+extern dma_addr_t usb_hcd_get_dcba_dma_addr(struct usb_device *udev);
+extern dma_addr_t
+usb_hcd_get_xfer_ring_dma_addr(struct usb_device *udev,
+ struct usb_host_endpoint *ep);
extern struct usb_hcd *usb_create_hcd(const struct hc_driver *driver,
struct device *dev, const char *bus_name);
@@ -483,7 +502,7 @@ extern void usb_hc_died(struct usb_hcd *hcd);
extern void usb_hcd_poll_rh_status(struct usb_hcd *hcd);
extern void usb_wakeup_notification(struct usb_device *hdev,
unsigned int portnum);
-
+extern void usb_flush_hub_wq(void);
extern void usb_hcd_start_port_resume(struct usb_bus *bus, int portnum);
extern void usb_hcd_end_port_resume(struct usb_bus *bus, int portnum);
diff --git a/include/linux/usb/msm_hsusb.h b/include/linux/usb/msm_hsusb.h
index 8c8f6854c993..44b6222db9a3 100644
--- a/include/linux/usb/msm_hsusb.h
+++ b/include/linux/usb/msm_hsusb.h
@@ -1,8 +1,8 @@
-/* linux/include/asm-arm/arch-msm/hsusb.h
+/* include/linux/usb/msm_hsusb.h
*
* Copyright (C) 2008 Google, Inc.
* Author: Brian Swetland <swetland@google.com>
- * Copyright (c) 2009-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2009-2016, The Linux Foundation. All rights reserved.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
@@ -20,8 +20,24 @@
#include <linux/extcon.h>
#include <linux/types.h>
+#include <linux/usb/ch9.h>
+#include <linux/usb/gadget.h>
#include <linux/usb/otg.h>
-#include <linux/clk.h>
+/*
+ * The following are bit fields describing the usb_request.udc_priv word.
+ * 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)
+
/**
* OTG control
@@ -99,6 +115,25 @@ enum usb_chg_type {
};
/**
+ * Supported USB controllers
+ */
+enum usb_ctrl {
+ DWC3_CTRL = 0, /* DWC3 controller */
+ CI_CTRL, /* ChipIdea controller */
+ HSIC_CTRL, /* HSIC controller */
+ NUM_CTRL,
+};
+
+
+/**
+ * USB ID state
+ */
+enum usb_id_state {
+ USB_ID_GROUND = 0,
+ USB_ID_FLOAT,
+};
+
+/**
* struct msm_otg_platform_data - platform device data
* for msm_otg driver.
* @phy_init_seq: PHY configuration sequence values. Value of -1 is reserved as
@@ -131,6 +166,21 @@ struct msm_usb_cable {
struct extcon_dev *extcon;
};
+
+/* phy related 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 USB_NUM_BUS_CLOCKS 3
+
/**
* struct msm_otg: OTG driver data. Shared by HCD and DCD.
* @otg: USB OTG Transceiver structure.
@@ -197,4 +247,94 @@ struct msm_otg {
struct notifier_block reboot;
};
+#ifdef CONFIG_USB_BAM
+void msm_bam_set_usb_host_dev(struct device *dev);
+void msm_bam_set_hsic_host_dev(struct device *dev);
+void msm_bam_wait_for_usb_host_prod_granted(void);
+void msm_bam_wait_for_hsic_host_prod_granted(void);
+bool msm_bam_hsic_lpm_ok(void);
+void msm_bam_usb_host_notify_on_resume(void);
+void msm_bam_hsic_host_notify_on_resume(void);
+bool msm_bam_hsic_host_pipe_empty(void);
+bool msm_usb_bam_enable(enum usb_ctrl ctrl, bool bam_enable);
+#else
+static inline void msm_bam_set_usb_host_dev(struct device *dev) {}
+static inline void msm_bam_set_hsic_host_dev(struct device *dev) {}
+static inline void msm_bam_wait_for_usb_host_prod_granted(void) {}
+static inline void msm_bam_wait_for_hsic_host_prod_granted(void) {}
+static inline bool msm_bam_hsic_lpm_ok(void) { return true; }
+static inline void msm_bam_hsic_host_notify_on_resume(void) {}
+static inline void msm_bam_usb_host_notify_on_resume(void) {}
+static inline bool msm_bam_hsic_host_pipe_empty(void) { return true; }
+static inline bool msm_usb_bam_enable(enum usb_ctrl ctrl, bool bam_enable)
+{
+ return true;
+}
+#endif
+
+/* CONFIG_PM */
+#ifdef CONFIG_PM
+static inline int get_pm_runtime_counter(struct device *dev)
+{
+ return atomic_read(&dev->power.usage_count);
+}
+#else /* !CONFIG_PM */
+static inline int get_pm_runtime_counter(struct device *dev) { return -ENOSYS; }
+#endif
+
+#ifdef CONFIG_USB_CI13XXX_MSM
+void msm_hw_bam_disable(bool bam_disable);
+void msm_usb_irq_disable(bool disable);
+#else
+static inline void msm_hw_bam_disable(bool bam_disable)
+{
+}
+
+static inline void msm_usb_irq_disable(bool disable)
+{
+}
+#endif
+
+#ifdef CONFIG_USB_DWC3_QCOM
+int msm_ep_config(struct usb_ep *ep);
+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, phys_addr_t 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 msm_data_fifo_config(struct usb_ep *ep, phys_addr_t addr,
+ u32 size, u8 dst_pipe_idx)
+{
+ return -ENODEV;
+}
+
+static inline int msm_ep_config(struct usb_ep *ep)
+{
+ 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
diff --git a/include/linux/usb/phy.h b/include/linux/usb/phy.h
index 31a8068c42a5..d25125402fda 100644
--- a/include/linux/usb/phy.h
+++ b/include/linux/usb/phy.h
@@ -44,6 +44,7 @@ enum usb_otg_state {
OTG_STATE_B_IDLE,
OTG_STATE_B_SRP_INIT,
OTG_STATE_B_PERIPHERAL,
+ OTG_STATE_B_SUSPEND,
/* extra dual-role default-b states */
OTG_STATE_B_WAIT_ACON,
@@ -122,6 +123,9 @@ struct usb_phy {
enum usb_device_speed speed);
int (*notify_disconnect)(struct usb_phy *x,
enum usb_device_speed speed);
+
+ /* reset the PHY clocks */
+ int (*reset)(struct usb_phy *x);
};
/**
@@ -196,6 +200,15 @@ usb_phy_vbus_off(struct usb_phy *x)
return x->set_vbus(x, false);
}
+static inline int
+usb_phy_reset(struct usb_phy *x)
+{
+ if (x && x->reset)
+ return x->reset(x);
+
+ return 0;
+}
+
/* for usb host and peripheral controller drivers */
#if IS_ENABLED(CONFIG_USB_PHY)
extern struct usb_phy *usb_get_phy(enum usb_phy_type type);
diff --git a/include/linux/usb/usb_qdss.h b/include/linux/usb/usb_qdss.h
new file mode 100644
index 000000000000..e01e6781eb21
--- /dev/null
+++ b/include/linux/usb/usb_qdss.h
@@ -0,0 +1,94 @@
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __LINUX_USB_QDSS_H
+#define __LINUX_USB_QDSS_H
+
+#include <linux/kernel.h>
+
+struct qdss_request {
+ char *buf;
+ int length;
+ int actual;
+ int status;
+ void *context;
+};
+
+struct usb_qdss_ch {
+ const char *name;
+ struct list_head list;
+ void (*notify)(void *priv, unsigned event, struct qdss_request *d_req,
+ struct usb_qdss_ch *);
+ void *priv;
+ void *priv_usb;
+ int app_conn;
+};
+
+enum qdss_state {
+ USB_QDSS_CONNECT,
+ USB_QDSS_DISCONNECT,
+ USB_QDSS_CTRL_READ_DONE,
+ USB_QDSS_DATA_WRITE_DONE,
+ USB_QDSS_CTRL_WRITE_DONE,
+};
+
+#if IS_ENABLED(CONFIG_USB_F_QDSS)
+struct usb_qdss_ch *usb_qdss_open(const char *name, void *priv,
+ void (*notify)(void *, unsigned, struct qdss_request *,
+ struct usb_qdss_ch *));
+void usb_qdss_close(struct usb_qdss_ch *ch);
+int usb_qdss_alloc_req(struct usb_qdss_ch *ch, int n_write, int n_read);
+void usb_qdss_free_req(struct usb_qdss_ch *ch);
+int usb_qdss_read(struct usb_qdss_ch *ch, struct qdss_request *d_req);
+int usb_qdss_write(struct usb_qdss_ch *ch, struct qdss_request *d_req);
+int usb_qdss_ctrl_write(struct usb_qdss_ch *ch, struct qdss_request *d_req);
+int usb_qdss_ctrl_read(struct usb_qdss_ch *ch, struct qdss_request *d_req);
+#else
+static inline struct usb_qdss_ch *usb_qdss_open(const char *name, void *priv,
+ void (*n)(void *, u32, struct qdss_request *, struct usb_qdss_ch *))
+{
+ return ERR_PTR(-ENODEV);
+}
+
+static inline int usb_qdss_read(struct usb_qdss_ch *c, struct qdss_request *d)
+{
+ return -ENODEV;
+}
+
+static inline int usb_qdss_write(struct usb_qdss_ch *c, struct qdss_request *d)
+{
+ return -ENODEV;
+}
+
+static inline int usb_qdss_ctrl_write(struct usb_qdss_ch *c,
+ struct qdss_request *d)
+{
+ return -ENODEV;
+}
+
+static inline int usb_qdss_ctrl_read(struct usb_qdss_ch *c,
+ struct qdss_request *d)
+{
+ return -ENODEV;
+}
+static inline int usb_qdss_alloc_req(struct usb_qdss_ch *c, int n_wr, int n_rd)
+{
+ return -ENODEV;
+}
+
+
+static inline void usb_qdss_close(struct usb_qdss_ch *ch) { }
+
+static inline void usb_qdss_free_req(struct usb_qdss_ch *ch) { }
+#endif /* CONFIG_USB_F_QDSS */
+
+#endif
diff --git a/include/linux/usb/usbdiag.h b/include/linux/usb/usbdiag.h
new file mode 100644
index 000000000000..f66762800368
--- /dev/null
+++ b/include/linux/usb/usbdiag.h
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2008-2010, 2012-2014, The Linux Foundation.
+ * All rights reserved.
+ *
+ * All source code in this file is licensed under the following license except
+ * where indicated.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * See the GNU General Public License for more details.
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, you can find it at http://www.fsf.org
+ */
+
+#ifndef _DRIVERS_USB_DIAG_H_
+#define _DRIVERS_USB_DIAG_H_
+
+#include <linux/err.h>
+
+#define DIAG_LEGACY "diag"
+#define DIAG_MDM "diag_mdm"
+#define DIAG_QSC "diag_qsc"
+#define DIAG_MDM2 "diag_mdm2"
+
+#define USB_DIAG_CONNECT 0
+#define USB_DIAG_DISCONNECT 1
+#define USB_DIAG_WRITE_DONE 2
+#define USB_DIAG_READ_DONE 3
+
+struct diag_request {
+ char *buf;
+ int length;
+ int actual;
+ int status;
+ void *context;
+};
+
+struct usb_diag_ch {
+ const char *name;
+ struct list_head list;
+ void (*notify)(void *priv, unsigned event, struct diag_request *d_req);
+ void *priv;
+ void *priv_usb;
+};
+
+#if IS_ENABLED(CONFIG_USB_F_DIAG)
+int usb_diag_request_size(struct usb_diag_ch *ch);
+struct usb_diag_ch *usb_diag_open(const char *name, void *priv,
+ void (*notify)(void *, unsigned, struct diag_request *));
+void usb_diag_close(struct usb_diag_ch *ch);
+int usb_diag_alloc_req(struct usb_diag_ch *ch, int n_write, int n_read);
+int usb_diag_read(struct usb_diag_ch *ch, struct diag_request *d_req);
+int usb_diag_write(struct usb_diag_ch *ch, struct diag_request *d_req);
+#else
+static inline struct usb_diag_ch *usb_diag_open(const char *name, void *priv,
+ void (*notify)(void *, unsigned, struct diag_request *))
+{
+ return ERR_PTR(-ENODEV);
+}
+static inline void usb_diag_close(struct usb_diag_ch *ch)
+{
+}
+static inline
+int usb_diag_alloc_req(struct usb_diag_ch *ch, int n_write, int n_read)
+{
+ return -ENODEV;
+}
+static inline
+int usb_diag_read(struct usb_diag_ch *ch, struct diag_request *d_req)
+{
+ return -ENODEV;
+}
+static inline
+int usb_diag_write(struct usb_diag_ch *ch, struct diag_request *d_req)
+{
+ return -ENODEV;
+}
+#endif /* CONFIG_USB_F_DIAG */
+#endif /* _DRIVERS_USB_DIAG_H_ */
diff --git a/include/linux/usb/usbpd.h b/include/linux/usb/usbpd.h
new file mode 100644
index 000000000000..3566a7a974d1
--- /dev/null
+++ b/include/linux/usb/usbpd.h
@@ -0,0 +1,159 @@
+/* Copyright (c) 2016, Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __LINUX_USB_USBPD_H
+#define __LINUX_USB_USBPD_H
+
+#include <linux/list.h>
+
+struct usbpd;
+
+/* Standard IDs */
+#define USBPD_SID 0xff00
+
+/* Structured VDM Command Type */
+enum usbpd_svdm_cmd_type {
+ SVDM_CMD_TYPE_INITIATOR,
+ SVDM_CMD_TYPE_RESP_ACK,
+ SVDM_CMD_TYPE_RESP_NAK,
+ SVDM_CMD_TYPE_RESP_BUSY,
+};
+
+/* Structured VDM Commands */
+#define USBPD_SVDM_DISCOVER_IDENTITY 0x1
+#define USBPD_SVDM_DISCOVER_SVIDS 0x2
+#define USBPD_SVDM_DISCOVER_MODES 0x3
+#define USBPD_SVDM_ENTER_MODE 0x4
+#define USBPD_SVDM_EXIT_MODE 0x5
+#define USBPD_SVDM_ATTENTION 0x6
+
+/*
+ * Implemented by client
+ */
+struct usbpd_svid_handler {
+ u16 svid;
+
+ /* Notified when VDM session established/reset; must be implemented */
+ void (*connect)(struct usbpd_svid_handler *hdlr);
+ void (*disconnect)(struct usbpd_svid_handler *hdlr);
+
+ /* Unstructured VDM */
+ void (*vdm_received)(struct usbpd_svid_handler *hdlr, u32 vdm_hdr,
+ const u32 *vdos, int num_vdos);
+
+ /* Structured VDM */
+ void (*svdm_received)(struct usbpd_svid_handler *hdlr, u8 cmd,
+ enum usbpd_svdm_cmd_type cmd_type, const u32 *vdos,
+ int num_vdos);
+
+ /* client should leave these blank; private members used by PD driver */
+ struct list_head entry;
+ bool discovered;
+};
+
+enum plug_orientation {
+ ORIENTATION_NONE,
+ ORIENTATION_CC1,
+ ORIENTATION_CC2,
+};
+
+#if IS_ENABLED(CONFIG_USB_PD_POLICY)
+/*
+ * Obtains an instance of usbpd from a DT phandle
+ */
+struct usbpd *devm_usbpd_get_by_phandle(struct device *dev,
+ const char *phandle);
+
+/*
+ * Called by client to handle specific SVID messages.
+ * Specify callback functions in the usbpd_svid_handler argument
+ */
+int usbpd_register_svid(struct usbpd *pd, struct usbpd_svid_handler *hdlr);
+
+void usbpd_unregister_svid(struct usbpd *pd, struct usbpd_svid_handler *hdlr);
+
+/*
+ * Transmit a VDM message.
+ */
+int usbpd_send_vdm(struct usbpd *pd, u32 vdm_hdr, const u32 *vdos,
+ int num_vdos);
+
+/*
+ * Transmit a Structured VDM message.
+ */
+int usbpd_send_svdm(struct usbpd *pd, u16 svid, u8 cmd,
+ enum usbpd_svdm_cmd_type cmd_type, int obj_pos,
+ const u32 *vdos, int num_vdos);
+
+/*
+ * Get current status of CC pin orientation.
+ *
+ * Return: ORIENTATION_CC1 or ORIENTATION_CC2 if attached,
+ * otherwise ORIENTATION_NONE if not attached
+ */
+enum plug_orientation usbpd_get_plug_orientation(struct usbpd *pd);
+#else
+static inline struct usbpd *devm_usbpd_get_by_phandle(struct device *dev,
+ const char *phandle)
+{
+ return ERR_PTR(-ENODEV);
+}
+
+static inline int usbpd_register_svid(struct usbpd *pd,
+ struct usbpd_svid_handler *hdlr)
+{
+ return -EINVAL;
+}
+
+static inline void usbpd_unregister_svid(struct usbpd *pd,
+ struct usbpd_svid_handler *hdlr)
+{
+}
+
+static inline int usbpd_send_vdm(struct usbpd *pd, u32 vdm_hdr, const u32 *vdos,
+ int num_vdos)
+{
+ return -EINVAL;
+}
+
+static inline int usbpd_send_svdm(struct usbpd *pd, u16 svid, u8 cmd,
+ enum usbpd_svdm_cmd_type cmd_type, int obj_pos,
+ const u32 *vdos, int num_vdos)
+{
+ return -EINVAL;
+}
+
+static inline enum plug_orientation usbpd_get_plug_orientation(struct usbpd *pd)
+{
+ return ORIENTATION_NONE;
+}
+#endif /* IS_ENABLED(CONFIG_USB_PD_POLICY) */
+
+/*
+ * Additional helpers for Enter/Exit Mode commands
+ */
+
+static inline int usbpd_enter_mode(struct usbpd *pd, u16 svid, int mode,
+ const u32 *vdo)
+{
+ return usbpd_send_svdm(pd, svid, USBPD_SVDM_ENTER_MODE,
+ SVDM_CMD_TYPE_INITIATOR, mode, vdo, vdo ? 1 : 0);
+}
+
+static inline int usbpd_exit_mode(struct usbpd *pd, u16 svid, int mode,
+ const u32 *vdo)
+{
+ return usbpd_send_svdm(pd, svid, USBPD_SVDM_EXIT_MODE,
+ SVDM_CMD_TYPE_INITIATOR, mode, vdo, vdo ? 1 : 0);
+}
+
+#endif /* __LINUX_USB_USBPD_H */