diff options
Diffstat (limited to 'include/linux/usb')
| -rw-r--r-- | include/linux/usb/cdc_ncm.h | 1 | ||||
| -rw-r--r-- | include/linux/usb/chipidea.h | 2 | ||||
| -rw-r--r-- | include/linux/usb/composite.h | 5 | ||||
| -rw-r--r-- | include/linux/usb/gadget.h | 34 | ||||
| -rw-r--r-- | include/linux/usb/gadget_configfs.h | 4 | ||||
| -rw-r--r-- | include/linux/usb/hcd.h | 6 | ||||
| -rw-r--r-- | include/linux/usb/isp1362.h | 47 | ||||
| -rw-r--r-- | include/linux/usb/mctp-usb.h | 30 | ||||
| -rw-r--r-- | include/linux/usb/musb.h | 2 | ||||
| -rw-r--r-- | include/linux/usb/pd.h | 69 | ||||
| -rw-r--r-- | include/linux/usb/quirks.h | 6 | ||||
| -rw-r--r-- | include/linux/usb/r8152.h | 2 | ||||
| -rw-r--r-- | include/linux/usb/tegra_usb_phy.h | 20 | ||||
| -rw-r--r-- | include/linux/usb/typec.h | 7 | ||||
| -rw-r--r-- | include/linux/usb/typec_altmode.h | 63 | ||||
| -rw-r--r-- | include/linux/usb/typec_dp.h | 1 | ||||
| -rw-r--r-- | include/linux/usb/typec_mux.h | 46 | ||||
| -rw-r--r-- | include/linux/usb/typec_tbt.h | 1 | ||||
| -rw-r--r-- | include/linux/usb/ulpi.h | 9 | ||||
| -rw-r--r-- | include/linux/usb/usbio.h | 177 | ||||
| -rw-r--r-- | include/linux/usb/usbnet.h | 7 | ||||
| -rw-r--r-- | include/linux/usb/uvc.h | 36 | ||||
| -rw-r--r-- | include/linux/usb/xhci-sideband.h | 111 |
23 files changed, 596 insertions, 90 deletions
diff --git a/include/linux/usb/cdc_ncm.h b/include/linux/usb/cdc_ncm.h index 2d207cb4837d..4ac082a63173 100644 --- a/include/linux/usb/cdc_ncm.h +++ b/include/linux/usb/cdc_ncm.h @@ -119,6 +119,7 @@ struct cdc_ncm_ctx { u32 timer_interval; u32 max_ndp_size; u8 is_ndp16; + u8 filtering_supported; union { struct usb_cdc_ncm_ndp16 *delayed_ndp16; struct usb_cdc_ncm_ndp32 *delayed_ndp32; diff --git a/include/linux/usb/chipidea.h b/include/linux/usb/chipidea.h index ebdfef124b2b..c6451191d2de 100644 --- a/include/linux/usb/chipidea.h +++ b/include/linux/usb/chipidea.h @@ -66,12 +66,14 @@ struct ci_hdrc_platform_data { #define CI_HDRC_HAS_PORTSC_PEC_MISSED BIT(17) #define CI_HDRC_FORCE_VBUS_ACTIVE_ALWAYS BIT(18) #define CI_HDRC_HAS_SHORT_PKT_LIMIT BIT(19) +#define CI_HDRC_OUT_BAND_WAKEUP BIT(20) enum usb_dr_mode dr_mode; #define CI_HDRC_CONTROLLER_RESET_EVENT 0 #define CI_HDRC_CONTROLLER_STOPPED_EVENT 1 #define CI_HDRC_IMX_HSIC_ACTIVE_EVENT 2 #define CI_HDRC_IMX_HSIC_SUSPEND_EVENT 3 #define CI_HDRC_CONTROLLER_VBUS_EVENT 4 +#define CI_HDRC_CONTROLLER_PULLUP_EVENT 5 int (*notify_event) (struct ci_hdrc *ci, unsigned event); struct regulator *reg_vbus; struct usb_otg_caps ci_otg_caps; diff --git a/include/linux/usb/composite.h b/include/linux/usb/composite.h index 6e38fb9d2117..c18041fafa52 100644 --- a/include/linux/usb/composite.h +++ b/include/linux/usb/composite.h @@ -237,7 +237,7 @@ struct usb_function { /* internals */ struct list_head list; DECLARE_BITMAP(endpoints, 32); - const struct usb_function_instance *fi; + struct usb_function_instance *fi; unsigned int bind_deactivated:1; }; @@ -339,9 +339,6 @@ int usb_add_config(struct usb_composite_dev *, struct usb_configuration *, int (*)(struct usb_configuration *)); -void usb_remove_config(struct usb_composite_dev *, - struct usb_configuration *); - /* predefined index for usb_composite_driver */ enum { USB_GADGET_MANUFACTURER_IDX = 0, diff --git a/include/linux/usb/gadget.h b/include/linux/usb/gadget.h index df33333650a0..8285b19a25e0 100644 --- a/include/linux/usb/gadget.h +++ b/include/linux/usb/gadget.h @@ -15,6 +15,7 @@ #ifndef __LINUX_USB_GADGET_H #define __LINUX_USB_GADGET_H +#include <linux/cleanup.h> #include <linux/configfs.h> #include <linux/device.h> #include <linux/errno.h> @@ -32,6 +33,7 @@ struct usb_ep; /** * struct usb_request - describes one i/o request + * @ep: The associated endpoint set by usb_ep_alloc_request(). * @buf: Buffer used for data. Always provide this; some controllers * only use PIO, or don't use DMA for some endpoints. * @dma: DMA address corresponding to 'buf'. If you don't set this @@ -98,6 +100,7 @@ struct usb_ep; */ struct usb_request { + struct usb_ep *ep; void *buf; unsigned length; dma_addr_t dma; @@ -291,6 +294,28 @@ static inline void usb_ep_fifo_flush(struct usb_ep *ep) /*-------------------------------------------------------------------------*/ +/** + * free_usb_request - frees a usb_request object and its buffer + * @req: the request being freed + * + * This helper function frees both the request's buffer and the request object + * itself by calling usb_ep_free_request(). Its signature is designed to be used + * with DEFINE_FREE() to enable automatic, scope-based cleanup for usb_request + * pointers. + */ +static inline void free_usb_request(struct usb_request *req) +{ + if (!req) + return; + + kfree(req->buf); + usb_ep_free_request(req->ep, req); +} + +DEFINE_FREE(free_usb_request, struct usb_request *, free_usb_request(_T)) + +/*-------------------------------------------------------------------------*/ + struct usb_dcd_config_params { __u8 bU1devExitLat; /* U1 Device exit Latency */ #define USB_DEFAULT_U1_DEV_EXIT_LAT 0x01 /* Less then 1 microsec */ @@ -351,6 +376,9 @@ struct usb_gadget_ops { * can handle. The UDC must support this and all slower speeds and lower * number of lanes. * @state: the state we are now (attached, suspended, configured, etc) + * @state_lock: Spinlock protecting the `state` and `teardown` members. + * @teardown: True if the device is undergoing teardown, used to prevent + * new work from being scheduled during cleanup. * @name: Identifies the controller hardware type. Used in diagnostics * and sometimes configuration. * @dev: Driver model state for this abstract device. @@ -426,6 +454,8 @@ struct usb_gadget { enum usb_ssp_rate max_ssp_rate; enum usb_device_state state; + spinlock_t state_lock; + bool teardown; const char *name; struct device dev; unsigned isoch_delay; @@ -860,10 +890,6 @@ container_of(str_item, struct gadget_string, item) int usb_descriptor_fillbuf(void *, unsigned, const struct usb_descriptor_header **); -/* build config descriptor from single descriptor vector */ -int usb_gadget_config_buf(const struct usb_config_descriptor *config, - void *buf, unsigned buflen, const struct usb_descriptor_header **desc); - /* copy a NULL-terminated vector of descriptors */ struct usb_descriptor_header **usb_copy_descriptors( struct usb_descriptor_header **); diff --git a/include/linux/usb/gadget_configfs.h b/include/linux/usb/gadget_configfs.h index 6b5d6838f865..23c1091e88c0 100644 --- a/include/linux/usb/gadget_configfs.h +++ b/include/linux/usb/gadget_configfs.h @@ -30,7 +30,7 @@ static ssize_t __struct##_##__name##_show(struct config_item *item, char *page) CONFIGFS_ATTR(struct_name##_, _name) #define USB_CONFIG_STRING_RW_OPS(struct_in) \ -static struct configfs_item_operations struct_in##_langid_item_ops = { \ +static const struct configfs_item_operations struct_in##_langid_item_ops = { \ .release = struct_in##_attr_release, \ }; \ \ @@ -86,7 +86,7 @@ static void struct_in##_strings_drop( \ config_item_put(item); \ } \ \ -static struct configfs_group_operations struct_in##_strings_ops = { \ +static const struct configfs_group_operations struct_in##_strings_ops = { \ .make_group = &struct_in##_strings_make, \ .drop_item = &struct_in##_strings_drop, \ }; \ diff --git a/include/linux/usb/hcd.h b/include/linux/usb/hcd.h index ac95e7c89df5..181db044c4d2 100644 --- a/include/linux/usb/hcd.h +++ b/include/linux/usb/hcd.h @@ -760,12 +760,6 @@ static inline void usbmon_urb_complete(struct usb_bus *bus, struct urb *urb, */ extern struct rw_semaphore ehci_cf_port_reset_rwsem; -/* Keep track of which host controller drivers are loaded */ -#define USB_UHCI_LOADED 0 -#define USB_OHCI_LOADED 1 -#define USB_EHCI_LOADED 2 -extern unsigned long usb_hcds_loaded; - #endif /* __KERNEL__ */ #endif /* __USB_CORE_HCD_H */ diff --git a/include/linux/usb/isp1362.h b/include/linux/usb/isp1362.h deleted file mode 100644 index 5356c4ae386e..000000000000 --- a/include/linux/usb/isp1362.h +++ /dev/null @@ -1,47 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * board initialization code should put one of these into dev->platform_data - * and place the isp1362 onto platform_bus. - */ - -#ifndef __LINUX_USB_ISP1362_H__ -#define __LINUX_USB_ISP1362_H__ - -struct isp1362_platform_data { - /* Enable internal pulldown resistors on downstream ports */ - unsigned sel15Kres:1; - /* Clock cannot be stopped */ - unsigned clknotstop:1; - /* On-chip overcurrent protection */ - unsigned oc_enable:1; - /* INT output polarity */ - unsigned int_act_high:1; - /* INT edge or level triggered */ - unsigned int_edge_triggered:1; - /* DREQ output polarity */ - unsigned dreq_act_high:1; - /* DACK input polarity */ - unsigned dack_act_high:1; - /* chip can be resumed via H_WAKEUP pin */ - unsigned remote_wakeup_connected:1; - /* Switch or not to switch (keep always powered) */ - unsigned no_power_switching:1; - /* Ganged port power switching (0) or individual port power switching (1) */ - unsigned power_switching_mode:1; - /* Given port_power, msec/2 after power on till power good */ - u8 potpg; - /* Hardware reset set/clear */ - void (*reset) (struct device *dev, int set); - /* Clock start/stop */ - void (*clock) (struct device *dev, int start); - /* Inter-io delay (ns). The chip is picky about access timings; it - * expects at least: - * 110ns delay between consecutive accesses to DATA_REG, - * 300ns delay between access to ADDR_REG and DATA_REG (registers) - * 462ns delay between access to ADDR_REG and DATA_REG (buffer memory) - * WE MUST NOT be activated during these intervals (even without CS!) - */ - void (*delay) (struct device *dev, unsigned int delay); -}; - -#endif diff --git a/include/linux/usb/mctp-usb.h b/include/linux/usb/mctp-usb.h new file mode 100644 index 000000000000..a2f6f1e04efb --- /dev/null +++ b/include/linux/usb/mctp-usb.h @@ -0,0 +1,30 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * mctp-usb.h - MCTP USB transport binding: common definitions, + * based on DMTF0283 specification: + * https://www.dmtf.org/sites/default/files/standards/documents/DSP0283_1.0.1.pdf + * + * These are protocol-level definitions, that may be shared between host + * and gadget drivers. + * + * Copyright (C) 2024-2025 Code Construct Pty Ltd + */ + +#ifndef __LINUX_USB_MCTP_USB_H +#define __LINUX_USB_MCTP_USB_H + +#include <linux/types.h> + +struct mctp_usb_hdr { + __be16 id; + u8 rsvd; + u8 len; +} __packed; + +#define MCTP_USB_XFER_SIZE 512 +#define MCTP_USB_BTU 68 +#define MCTP_USB_MTU_MIN MCTP_USB_BTU +#define MCTP_USB_MTU_MAX (U8_MAX - sizeof(struct mctp_usb_hdr)) +#define MCTP_USB_DMTF_ID 0x1ab4 + +#endif /* __LINUX_USB_MCTP_USB_H */ diff --git a/include/linux/usb/musb.h b/include/linux/usb/musb.h index 3963e55e88a3..fbdef950f06c 100644 --- a/include/linux/usb/musb.h +++ b/include/linux/usb/musb.h @@ -61,7 +61,7 @@ struct musb_hdrc_eps_bits { }; struct musb_hdrc_config { - struct musb_fifo_cfg *fifo_cfg; /* board fifo configuration */ + const struct musb_fifo_cfg *fifo_cfg; /* board fifo configuration */ unsigned fifo_cfg_size; /* size of the fifo configuration */ /* MUSB configuration-specific details */ diff --git a/include/linux/usb/pd.h b/include/linux/usb/pd.h index 3068c3084eb6..6ccd1b2af993 100644 --- a/include/linux/usb/pd.h +++ b/include/linux/usb/pd.h @@ -6,6 +6,7 @@ #ifndef __LINUX_USB_PD_H #define __LINUX_USB_PD_H +#include <linux/bitfield.h> #include <linux/kernel.h> #include <linux/types.h> #include <linux/usb/typec.h> @@ -271,9 +272,11 @@ enum pd_pdo_type { enum pd_apdo_type { APDO_TYPE_PPS = 0, + APDO_TYPE_EPR_AVS = 1, + APDO_TYPE_SPR_AVS = 2, }; -#define PDO_APDO_TYPE_SHIFT 28 /* Only valid value currently is 0x0 - PPS */ +#define PDO_APDO_TYPE_SHIFT 28 #define PDO_APDO_TYPE_MASK 0x3 #define PDO_APDO_TYPE(t) ((t) << PDO_APDO_TYPE_SHIFT) @@ -297,6 +300,35 @@ enum pd_apdo_type { PDO_PPS_APDO_MIN_VOLT(min_mv) | PDO_PPS_APDO_MAX_VOLT(max_mv) | \ PDO_PPS_APDO_MAX_CURR(max_ma)) +/* + * Applicable only to EPR AVS APDO source cap as per + * Table 6.15 EPR Adjustable Voltage Supply APDO – Source + */ +#define PDO_EPR_AVS_APDO_PEAK_CURRENT GENMASK(27, 26) + +/* + * Applicable to both EPR AVS APDO source and sink cap as per + * Table 6.15 EPR Adjustable Voltage Supply APDO – Source + * Table 6.22 EPR Adjustable Voltage Supply APDO – Sink + */ +#define PDO_EPR_AVS_APDO_MAX_VOLT GENMASK(25, 17) /* 100mV unit */ +#define PDO_EPR_AVS_APDO_MIN_VOLT GENMASK(15, 8) /* 100mV unit */ +#define PDO_EPR_AVS_APDO_PDP GENMASK(7, 0) /* 1W unit */ + +/* + * Applicable only SPR AVS APDO source cap as per + * Table 6.14 SPR Adjustable Voltage Supply APDO – Source + */ +#define PDO_SPR_AVS_APDO_PEAK_CURRENT GENMASK(27, 26) + +/* + * Applicable to both SPR AVS APDO source and sink cap as per + * Table 6.14 SPR Adjustable Voltage Supply APDO – Source + * Table 6.21 SPR Adjustable Voltage Supply APDO – Sink + */ +#define PDO_SPR_AVS_APDO_9V_TO_15V_MAX_CURR GENMASK(19, 10) /* 10mA unit */ +#define PDO_SPR_AVS_APDO_15V_TO_20V_MAX_CURR GENMASK(9, 0) /* 10mA unit */ + static inline enum pd_pdo_type pdo_type(u32 pdo) { return (pdo >> PDO_TYPE_SHIFT) & PDO_TYPE_MASK; @@ -350,6 +382,41 @@ static inline unsigned int pdo_pps_apdo_max_current(u32 pdo) PDO_PPS_APDO_CURR_MASK) * 50; } +static inline unsigned int pdo_epr_avs_apdo_src_peak_current(u32 pdo) +{ + return FIELD_GET(PDO_EPR_AVS_APDO_PEAK_CURRENT, pdo); +} + +static inline unsigned int pdo_epr_avs_apdo_min_voltage_mv(u32 pdo) +{ + return FIELD_GET(PDO_EPR_AVS_APDO_MIN_VOLT, pdo) * 100; +} + +static inline unsigned int pdo_epr_avs_apdo_max_voltage_mv(u32 pdo) +{ + return FIELD_GET(PDO_EPR_AVS_APDO_MIN_VOLT, pdo) * 100; +} + +static inline unsigned int pdo_epr_avs_apdo_pdp_w(u32 pdo) +{ + return FIELD_GET(PDO_EPR_AVS_APDO_PDP, pdo); +} + +static inline unsigned int pdo_spr_avs_apdo_src_peak_current(u32 pdo) +{ + return FIELD_GET(PDO_SPR_AVS_APDO_PEAK_CURRENT, pdo); +} + +static inline unsigned int pdo_spr_avs_apdo_9v_to_15v_max_current_ma(u32 pdo) +{ + return FIELD_GET(PDO_SPR_AVS_APDO_9V_TO_15V_MAX_CURR, pdo) * 10; +} + +static inline unsigned int pdo_spr_avs_apdo_15v_to_20v_max_current_ma(u32 pdo) +{ + return FIELD_GET(PDO_SPR_AVS_APDO_15V_TO_20V_MAX_CURR, pdo) * 10; +} + /* RDO: Request Data Object */ #define RDO_OBJ_POS_SHIFT 28 #define RDO_OBJ_POS_MASK 0x7 diff --git a/include/linux/usb/quirks.h b/include/linux/usb/quirks.h index 59409c1fc3de..b3cc7beab4a3 100644 --- a/include/linux/usb/quirks.h +++ b/include/linux/usb/quirks.h @@ -75,4 +75,10 @@ /* short SET_ADDRESS request timeout */ #define USB_QUIRK_SHORT_SET_ADDRESS_REQ_TIMEOUT BIT(16) +/* skip BOS descriptor request */ +#define USB_QUIRK_NO_BOS BIT(17) + +/* Device claims zero configurations, forcing to 1 */ +#define USB_QUIRK_FORCE_ONE_CONFIG BIT(18) + #endif /* __LINUX_USB_QUIRKS_H */ diff --git a/include/linux/usb/r8152.h b/include/linux/usb/r8152.h index 33a4c146dc19..1502b2a355f9 100644 --- a/include/linux/usb/r8152.h +++ b/include/linux/usb/r8152.h @@ -30,7 +30,9 @@ #define VENDOR_ID_NVIDIA 0x0955 #define VENDOR_ID_TPLINK 0x2357 #define VENDOR_ID_DLINK 0x2001 +#define VENDOR_ID_DELL 0x413c #define VENDOR_ID_ASUS 0x0b05 +#define VENDOR_ID_TRENDNET 0x20f4 #if IS_REACHABLE(CONFIG_USB_RTL8152) extern u8 rtl8152_get_version(struct usb_interface *intf); diff --git a/include/linux/usb/tegra_usb_phy.h b/include/linux/usb/tegra_usb_phy.h index e6c14f2b1f9b..6343f88df5de 100644 --- a/include/linux/usb/tegra_usb_phy.h +++ b/include/linux/usb/tegra_usb_phy.h @@ -23,6 +23,11 @@ struct gpio_desc; * requires_extra_tuning_parameters: true if xcvr_hsslew, hssquelch_level * and hsdiscon_level should be set for adequate signal quality * requires_pmc_ao_power_up: true if USB AO is powered down by default + * uhsic_registers_offset: for Tegra30+ where HSIC registers were offset + * comparing to Tegra20 by 0x400, since Tegra20 has no UTMIP on PHY2 + * uhsic_tx_rtune: fine tuned 50 Ohm termination resistor for NMOS/PMOS driver + * uhsic_pts_value: parallel transceiver select enumeration value + * portsc1_offset: register offset of PORTSC1 */ struct tegra_phy_soc_config { @@ -31,6 +36,10 @@ struct tegra_phy_soc_config { bool requires_usbmode_setup; bool requires_extra_tuning_parameters; bool requires_pmc_ao_power_up; + u32 uhsic_registers_offset; + u32 uhsic_tx_rtune; + u32 uhsic_pts_value; + u32 portsc1_offset; }; struct tegra_utmip_config { @@ -72,7 +81,7 @@ struct tegra_usb_phy { struct usb_phy *ulpi; struct usb_phy u_phy; bool is_legacy_phy; - bool is_ulpi_phy; + enum usb_phy_interface phy_type; struct gpio_desc *reset_gpio; struct reset_control *pad_rst; bool wakeup_enabled; @@ -80,13 +89,4 @@ struct tegra_usb_phy { bool powered_on; }; -void tegra_usb_phy_preresume(struct usb_phy *phy); - -void tegra_usb_phy_postresume(struct usb_phy *phy); - -void tegra_ehci_phy_restore_start(struct usb_phy *phy, - enum tegra_usb_phy_port_speed port_speed); - -void tegra_ehci_phy_restore_end(struct usb_phy *phy); - #endif /* __TEGRA_USB_PHY_H */ diff --git a/include/linux/usb/typec.h b/include/linux/usb/typec.h index 252af3f77039..d61ec38216fa 100644 --- a/include/linux/usb/typec.h +++ b/include/linux/usb/typec.h @@ -20,12 +20,15 @@ struct typec_port; struct typec_altmode_ops; struct typec_cable_ops; +struct bus_type; struct fwnode_handle; struct device; struct usb_power_delivery; struct usb_power_delivery_desc; +extern const struct bus_type typec_bus; + enum typec_port_type { TYPEC_PORT_SRC, TYPEC_PORT_SNK, @@ -152,6 +155,7 @@ struct typec_altmode_desc { /* Only used with ports */ enum typec_port_data roles; bool inactive; + bool mode_selection; }; void typec_partner_set_pd_revision(struct typec_partner *partner, u16 pd_revision); @@ -287,6 +291,7 @@ enum usb_pd_svdm_ver { * @prefer_role: Initial role preference (DRP ports). * @accessory: Supported Accessory Modes * @usb_capability: Supported USB Modes + * @no_mode_control: Ability to manage Alternate Modes * @fwnode: Optional fwnode of the port * @driver_data: Private pointer for driver specific info * @pd: Optional USB Power Delivery Support @@ -304,6 +309,7 @@ struct typec_capability { enum typec_accessory accessory[TYPEC_MAX_ACCESSORY]; unsigned int orientation_aware:1; u8 usb_capability; + bool no_mode_control; struct fwnode_handle *fwnode; void *driver_data; @@ -337,6 +343,7 @@ struct typec_plug *typec_register_plug(struct typec_cable *cable, void typec_unregister_plug(struct typec_plug *plug); void typec_set_data_role(struct typec_port *port, enum typec_data_role role); +enum typec_data_role typec_get_data_role(struct typec_port *port); void typec_set_pwr_role(struct typec_port *port, enum typec_role role); void typec_set_vconn_role(struct typec_port *port, enum typec_role role); void typec_set_pwr_opmode(struct typec_port *port, enum typec_pwr_opmode mode); diff --git a/include/linux/usb/typec_altmode.h b/include/linux/usb/typec_altmode.h index b3c0866ea70f..0513d333b797 100644 --- a/include/linux/usb/typec_altmode.h +++ b/include/linux/usb/typec_altmode.h @@ -9,6 +9,14 @@ #define MODE_DISCOVERY_MAX 6 +extern const struct device_type typec_port_altmode_dev_type; +extern const struct device_type typec_plug_altmode_dev_type; +extern const struct device_type typec_partner_altmode_dev_type; + +#define is_typec_port_altmode(dev) ((dev)->type == &typec_port_altmode_dev_type) +#define is_typec_plug_altmode(dev) ((dev)->type == &typec_plug_altmode_dev_type) +#define is_typec_partner_altmode(dev) ((dev)->type == &typec_partner_altmode_dev_type) + struct typec_altmode_ops; /** @@ -28,6 +36,8 @@ struct typec_altmode { int mode; u32 vdo; unsigned int active:1; + u8 priority; + bool mode_selection; char *desc; const struct typec_altmode_ops *ops; @@ -173,6 +183,19 @@ typec_altmode_get_svdm_version(struct typec_altmode *altmode) } /** + * typec_altmode_get_data_role - Get port data role + * @altmode: Handle to the alternate mode + * + * Alt Mode drivers should only issue Enter Mode through the port if they are + * the DFP. + */ +static inline enum typec_data_role +typec_altmode_get_data_role(struct typec_altmode *altmode) +{ + return typec_get_data_role(typec_altmode2port(altmode)); +} + +/** * struct typec_altmode_driver - USB Type-C alternate mode device driver * @id_table: Null terminated array of SVIDs * @probe: Callback for device binding @@ -218,4 +241,44 @@ void typec_altmode_unregister_driver(struct typec_altmode_driver *drv); module_driver(__typec_altmode_driver, typec_altmode_register_driver, \ typec_altmode_unregister_driver) +/** + * typec_mode_selection_start - Start an alternate mode selection process + * @partner: Handle to the Type-C partner device + * @delay: Delay between mode entry/exit attempts, ms + * @timeout: Timeout for a mode entry attempt, ms + * + * This function initiates the process of attempting to enter an Alternate Mode + * supported by the connected Type-C partner. + * Returns 0 on success, or a negative error code on failure. + */ +int typec_mode_selection_start(struct typec_partner *partner, + const unsigned int delay, const unsigned int timeout); + +/** + * typec_altmode_state_update - Report the current status of an Alternate Mode + * negotiation + * @partner: Handle to the Type-C partner device + * @svid: Standard or Vendor ID of the Alternate Mode. A value of 0 should be + * passed if no mode is currently active + * @result: Result of the entry operation. This should be 0 on success, or a + * negative error code if the negotiation failed + * + * This function should be called by an Alternate Mode driver to report the + * result of an asynchronous alternate mode entry request. It signals what the + * current active SVID is (or 0 if none) and the success or failure status of + * the last attempt. + */ +void typec_altmode_state_update(struct typec_partner *partner, const u16 svid, + const int result); + +/** + * typec_mode_selection_delete - Delete an alternate mode selection instance + * @partner: Handle to the Type-C partner device. + * + * This function cancels a pending alternate mode selection request that was + * previously started with typec_mode_selection_start(). + * This is typically called when the partner disconnects. + */ +void typec_mode_selection_delete(struct typec_partner *partner); + #endif /* __USB_TYPEC_ALTMODE_H */ diff --git a/include/linux/usb/typec_dp.h b/include/linux/usb/typec_dp.h index f2da264d9c14..acb0ad03bdac 100644 --- a/include/linux/usb/typec_dp.h +++ b/include/linux/usb/typec_dp.h @@ -57,6 +57,7 @@ enum { DP_PIN_ASSIGN_D, DP_PIN_ASSIGN_E, DP_PIN_ASSIGN_F, /* Not supported after v1.0b */ + DP_PIN_ASSIGN_MAX, }; /* DisplayPort alt mode specific commands */ diff --git a/include/linux/usb/typec_mux.h b/include/linux/usb/typec_mux.h index 2489a7857d8e..aa9ebb7e2fe0 100644 --- a/include/linux/usb/typec_mux.h +++ b/include/linux/usb/typec_mux.h @@ -3,6 +3,7 @@ #ifndef __USB_TYPEC_MUX #define __USB_TYPEC_MUX +#include <linux/err.h> #include <linux/property.h> #include <linux/usb/typec.h> @@ -24,16 +25,13 @@ struct typec_switch_desc { void *drvdata; }; +#if IS_ENABLED(CONFIG_TYPEC) + struct typec_switch *fwnode_typec_switch_get(struct fwnode_handle *fwnode); void typec_switch_put(struct typec_switch *sw); int typec_switch_set(struct typec_switch *sw, enum typec_orientation orientation); -static inline struct typec_switch *typec_switch_get(struct device *dev) -{ - return fwnode_typec_switch_get(dev_fwnode(dev)); -} - struct typec_switch_dev * typec_switch_register(struct device *parent, const struct typec_switch_desc *desc); @@ -42,6 +40,44 @@ void typec_switch_unregister(struct typec_switch_dev *sw); void typec_switch_set_drvdata(struct typec_switch_dev *sw, void *data); void *typec_switch_get_drvdata(struct typec_switch_dev *sw); +#else + +static inline struct typec_switch * +fwnode_typec_switch_get(struct fwnode_handle *fwnode) +{ + return NULL; +} + +static inline void typec_switch_put(struct typec_switch *sw) {} + +static inline int typec_switch_set(struct typec_switch *sw, + enum typec_orientation orientation) +{ + return 0; +} + +static inline struct typec_switch_dev * +typec_switch_register(struct device *parent, + const struct typec_switch_desc *desc) +{ + return ERR_PTR(-EOPNOTSUPP); +} + +static inline void typec_switch_unregister(struct typec_switch_dev *sw) {} + +static inline void typec_switch_set_drvdata(struct typec_switch_dev *sw, void *data) {} +static inline void *typec_switch_get_drvdata(struct typec_switch_dev *sw) +{ + return ERR_PTR(-EOPNOTSUPP); +} + +#endif /* CONFIG_TYPEC */ + +static inline struct typec_switch *typec_switch_get(struct device *dev) +{ + return fwnode_typec_switch_get(dev_fwnode(dev)); +} + struct typec_mux_state { struct typec_altmode *alt; unsigned long mode; diff --git a/include/linux/usb/typec_tbt.h b/include/linux/usb/typec_tbt.h index 55dcea12082c..0b570f1b8bc8 100644 --- a/include/linux/usb/typec_tbt.h +++ b/include/linux/usb/typec_tbt.h @@ -55,6 +55,7 @@ struct typec_thunderbolt_data { /* TBT3 Device Enter Mode VDO bits */ #define TBT_ENTER_MODE_CABLE_SPEED(s) TBT_SET_CABLE_SPEED(s) +#define TBT_ENTER_MODE_UNI_DIR_LSRX BIT(23) #define TBT_ENTER_MODE_ACTIVE_CABLE BIT(24) #endif /* __USB_TYPEC_TBT_H */ diff --git a/include/linux/usb/ulpi.h b/include/linux/usb/ulpi.h index 5050f502c1ed..4b651065738a 100644 --- a/include/linux/usb/ulpi.h +++ b/include/linux/usb/ulpi.h @@ -49,19 +49,10 @@ /*-------------------------------------------------------------------------*/ #if IS_ENABLED(CONFIG_USB_ULPI) -struct usb_phy *otg_ulpi_create(struct usb_phy_io_ops *ops, - unsigned int flags); - struct usb_phy *devm_otg_ulpi_create(struct device *dev, struct usb_phy_io_ops *ops, unsigned int flags); #else -static inline struct usb_phy *otg_ulpi_create(struct usb_phy_io_ops *ops, - unsigned int flags) -{ - return NULL; -} - static inline struct usb_phy *devm_otg_ulpi_create(struct device *dev, struct usb_phy_io_ops *ops, unsigned int flags) diff --git a/include/linux/usb/usbio.h b/include/linux/usb/usbio.h new file mode 100644 index 000000000000..6c4e7c246d58 --- /dev/null +++ b/include/linux/usb/usbio.h @@ -0,0 +1,177 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2025 Intel Corporation. + * + */ + +#ifndef _LINUX_USBIO_H_ +#define _LINUX_USBIO_H_ + +#include <linux/auxiliary_bus.h> +#include <linux/byteorder/generic.h> +#include <linux/list.h> +#include <linux/types.h> + +/*********************** + * USBIO Clients Names * + ***********************/ +#define USBIO_GPIO_CLIENT "usbio-gpio" +#define USBIO_I2C_CLIENT "usbio-i2c" + +/**************** + * USBIO quirks * + ****************/ +#define USBIO_QUIRK_BULK_MAXP_63 BIT(0) /* Force bulk endpoint maxp to 63 */ +#define USBIO_QUIRK_I2C_NO_INIT_ACK BIT(8) /* Do not ask for ack on I2C init */ +#define USBIO_QUIRK_I2C_MAX_RW_LEN_52 BIT(9) /* Set i2c-adapter max r/w len to 52 */ +#define USBIO_QUIRK_I2C_USE_CHUNK_LEN BIT(10) /* Send chunk-len for split xfers */ +#define USBIO_QUIRK_I2C_ALLOW_400KHZ BIT(11) /* Override desc, allowing 400 KHz */ + +/************************** + * USBIO Type Definitions * + **************************/ + +/* USBIO Packet Type */ +#define USBIO_PKTTYPE_CTRL 1 +#define USBIO_PKTTYPE_DBG 2 +#define USBIO_PKTTYPE_GPIO 3 +#define USBIO_PKTTYPE_I2C 4 + +/* USBIO Packet Header */ +struct usbio_packet_header { + u8 type; + u8 cmd; + u8 flags; +} __packed; + +/* USBIO Control Transfer Packet */ +struct usbio_ctrl_packet { + struct usbio_packet_header header; + u8 len; + u8 data[] __counted_by(len); +} __packed; + +/* USBIO Bulk Transfer Packet */ +struct usbio_bulk_packet { + struct usbio_packet_header header; + __le16 len; + u8 data[] __counted_by(len); +} __packed; + +/* USBIO GPIO commands */ +enum usbio_gpio_cmd { + USBIO_GPIOCMD_DEINIT, + USBIO_GPIOCMD_INIT, + USBIO_GPIOCMD_READ, + USBIO_GPIOCMD_WRITE, + USBIO_GPIOCMD_END +}; + +/* USBIO GPIO config */ +enum usbio_gpio_pincfg { + USBIO_GPIO_PINCFG_DEFAULT, + USBIO_GPIO_PINCFG_PULLUP, + USBIO_GPIO_PINCFG_PULLDOWN, + USBIO_GPIO_PINCFG_PUSHPULL +}; + +#define USBIO_GPIO_PINCFG_SHIFT 2 +#define USBIO_GPIO_PINCFG_MASK (0x3 << USBIO_GPIO_PINCFG_SHIFT) +#define USBIO_GPIO_SET_PINCFG(pincfg) \ + (((pincfg) << USBIO_GPIO_PINCFG_SHIFT) & USBIO_GPIO_PINCFG_MASK) + +enum usbio_gpio_pinmode { + USBIO_GPIO_PINMOD_INVAL, + USBIO_GPIO_PINMOD_INPUT, + USBIO_GPIO_PINMOD_OUTPUT, + USBIO_GPIO_PINMOD_MAXVAL +}; + +#define USBIO_GPIO_PINMOD_MASK 0x3 +#define USBIO_GPIO_SET_PINMOD(pin) (pin & USBIO_GPIO_PINMOD_MASK) + +/************************* + * USBIO GPIO Controller * + *************************/ + +#define USBIO_MAX_GPIOBANKS 5 +#define USBIO_GPIOSPERBANK 32 + +struct usbio_gpio_bank_desc { + u8 id; + u8 pins; + __le32 bmap; +} __packed; + +struct usbio_gpio_init { + u8 bankid; + u8 config; + u8 pincount; + u8 pin; +} __packed; + +struct usbio_gpio_rw { + u8 bankid; + u8 pincount; + u8 pin; + __le32 value; +} __packed; + +/* USBIO I2C commands */ +enum usbio_i2c_cmd { + USBIO_I2CCMD_UNINIT, + USBIO_I2CCMD_INIT, + USBIO_I2CCMD_READ, + USBIO_I2CCMD_WRITE, + USBIO_I2CCMD_END +}; + +/************************ + * USBIO I2C Controller * + ************************/ + +#define USBIO_MAX_I2CBUSES 5 + +#define USBIO_I2C_BUS_ADDR_CAP_10B BIT(3) /* 10bit address support */ +#define USBIO_I2C_BUS_MODE_CAP_MASK 0x3 +#define USBIO_I2C_BUS_MODE_CAP_SM 0 /* Standard Mode */ +#define USBIO_I2C_BUS_MODE_CAP_FM 1 /* Fast Mode */ +#define USBIO_I2C_BUS_MODE_CAP_FMP 2 /* Fast Mode+ */ +#define USBIO_I2C_BUS_MODE_CAP_HSM 3 /* High-Speed Mode */ + +struct usbio_i2c_bus_desc { + u8 id; + u8 caps; +} __packed; + +struct usbio_i2c_uninit { + u8 busid; + __le16 config; +} __packed; + +struct usbio_i2c_init { + u8 busid; + __le16 config; + __le32 speed; +} __packed; + +struct usbio_i2c_rw { + u8 busid; + __le16 config; + __le16 size; + u8 data[] __counted_by(size); +} __packed; + +int usbio_control_msg(struct auxiliary_device *adev, u8 type, u8 cmd, + const void *obuf, u16 obuf_len, void *ibuf, u16 ibuf_len); + +int usbio_bulk_msg(struct auxiliary_device *adev, u8 type, u8 cmd, bool last, + const void *obuf, u16 obuf_len, void *ibuf, u16 ibuf_len); + +int usbio_acquire(struct auxiliary_device *adev); +void usbio_release(struct auxiliary_device *adev); +void usbio_get_txrxbuf_len(struct auxiliary_device *adev, u16 *txbuf_len, u16 *rxbuf_len); +unsigned long usbio_get_quirks(struct auxiliary_device *adev); +void usbio_acpi_bind(struct auxiliary_device *adev, const struct acpi_device_id *hids); + +#endif diff --git a/include/linux/usb/usbnet.h b/include/linux/usb/usbnet.h index 0b9f1e598e3a..bbf799ccf3b3 100644 --- a/include/linux/usb/usbnet.h +++ b/include/linux/usb/usbnet.h @@ -14,6 +14,7 @@ #include <linux/skbuff.h> #include <linux/types.h> #include <linux/usb.h> +#include <linux/spinlock.h> /* interface from usbnet core to each USB networking link we handle */ struct usbnet { @@ -58,7 +59,8 @@ struct usbnet { unsigned interrupt_count; struct mutex interrupt_mutex; struct usb_anchor deferred; - struct tasklet_struct bh; + struct work_struct bh_work; + spinlock_t bql_spinlock; struct work_struct kevent; unsigned long flags; @@ -76,6 +78,7 @@ struct usbnet { # define EVENT_LINK_CHANGE 11 # define EVENT_SET_RX_MODE 12 # define EVENT_NO_IP_ALIGN 13 +# define EVENT_LINK_CARRIER_ON 14 /* This one is special, as it indicates that the device is going away * there are cyclic dependencies between tasklet, timer and bh * that must be broken @@ -129,6 +132,7 @@ struct driver_info { #define FLAG_MULTI_PACKET 0x2000 #define FLAG_RX_ASSEMBLE 0x4000 /* rx packets may span >1 frames */ #define FLAG_NOARP 0x8000 /* device can't do ARP */ +#define FLAG_NOMAXMTU 0x10000 /* allow max_mtu above hard_mtu */ /* init device ... can sleep, or cause probe() failure */ int (*bind)(struct usbnet *, struct usb_interface *); @@ -287,6 +291,7 @@ extern u32 usbnet_get_msglevel(struct net_device *); extern void usbnet_set_msglevel(struct net_device *, u32); extern void usbnet_set_rx_mode(struct net_device *net); extern void usbnet_get_drvinfo(struct net_device *, struct ethtool_drvinfo *); +extern int usbnet_mii_ioctl(struct net_device *net, struct ifreq *rq, int cmd); extern int usbnet_nway_reset(struct net_device *net); extern int usbnet_manage_power(struct usbnet *, int); diff --git a/include/linux/usb/uvc.h b/include/linux/usb/uvc.h index bce95153e5a6..05bfebab42b6 100644 --- a/include/linux/usb/uvc.h +++ b/include/linux/usb/uvc.h @@ -10,6 +10,14 @@ /* ------------------------------------------------------------------------ * GUIDs + * + * The GUID returned by lsusb can be converted to this format with the + * following python snippet: + * + * import uuid + * id = "{01234567-89ab-cdef-0123-456789abcdef}" + * le = uuid.UUID(id).bytes_le + * print("{" + ", ".join([f"0x{b:02x}" for b in le]) + "}") */ #define UVC_GUID_UVC_CAMERA \ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ @@ -29,6 +37,31 @@ #define UVC_GUID_EXT_GPIO_CONTROLLER \ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x03} +#define UVC_GUID_CHROMEOS_XU \ + {0x24, 0xe9, 0xd7, 0x74, 0xc9, 0x49, 0x45, 0x4a, \ + 0x98, 0xa3, 0xc8, 0x07, 0x7e, 0x05, 0x1c, 0xa3} +#define UVC_GUID_MSXU_1_5 \ + {0xdc, 0x95, 0x3f, 0x0f, 0x32, 0x26, 0x4e, 0x4c, \ + 0x92, 0xc9, 0xa0, 0x47, 0x82, 0xf4, 0x3b, 0xc8} + +/* https://learn.microsoft.com/en-us/windows-hardware/drivers/stream/uvc-extensions-1-5#222-extension-unit-controls */ +#define UVC_MSXU_CONTROL_FOCUS 0x01 +#define UVC_MSXU_CONTROL_EXPOSURE 0x02 +#define UVC_MSXU_CONTROL_EVCOMPENSATION 0x03 +#define UVC_MSXU_CONTROL_WHITEBALANCE 0x04 +#define UVC_MSXU_CONTROL_FACE_AUTHENTICATION 0x06 +#define UVC_MSXU_CONTROL_CAMERA_EXTRINSICS 0x07 +#define UVC_MSXU_CONTROL_CAMERA_INTRINSICS 0x08 +#define UVC_MSXU_CONTROL_METADATA 0x09 +#define UVC_MSXU_CONTROL_IR_TORCH 0x0a +#define UVC_MSXU_CONTROL_DIGITALWINDOW 0x0b +#define UVC_MSXU_CONTROL_DIGITALWINDOW_CONFIG 0x0c +#define UVC_MSXU_CONTROL_VIDEO_HDR 0x0d +#define UVC_MSXU_CONTROL_FRAMERATE_THROTTLE 0x0e +#define UVC_MSXU_CONTROL_FIELDOFVIEW2_CONFIG 0x0f +#define UVC_MSXU_CONTROL_FIELDOFVIEW2 0x10 + +#define UVC_CROSXU_CONTROL_IQ_PROFILE 0x04 #define UVC_GUID_FORMAT_MJPEG \ { 'M', 'J', 'P', 'G', 0x00, 0x00, 0x10, 0x00, \ @@ -105,6 +138,9 @@ #define UVC_GUID_FORMAT_M420 \ { 'M', '4', '2', '0', 0x00, 0x00, 0x10, 0x00, \ 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71} +#define UVC_GUID_FORMAT_P010 \ + { 'P', '0', '1', '0', 0x00, 0x00, 0x10, 0x00, \ + 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71} #define UVC_GUID_FORMAT_H264 \ { 'H', '2', '6', '4', 0x00, 0x00, 0x10, 0x00, \ diff --git a/include/linux/usb/xhci-sideband.h b/include/linux/usb/xhci-sideband.h new file mode 100644 index 000000000000..005257085dcb --- /dev/null +++ b/include/linux/usb/xhci-sideband.h @@ -0,0 +1,111 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * xHCI host controller sideband support + * + * Copyright (c) 2023-2025, Intel Corporation. + * + * Author: Mathias Nyman <mathias.nyman@linux.intel.com> + */ +#ifndef __LINUX_XHCI_SIDEBAND_H +#define __LINUX_XHCI_SIDEBAND_H + +#include <linux/scatterlist.h> +#include <linux/usb.h> +#include <linux/usb/hcd.h> + +#define EP_CTX_PER_DEV 31 /* FIXME defined twice, from xhci.h */ + +struct xhci_sideband; + +enum xhci_sideband_type { + XHCI_SIDEBAND_AUDIO, + XHCI_SIDEBAND_VENDOR, +}; + +enum xhci_sideband_notify_type { + XHCI_SIDEBAND_XFER_RING_FREE, +}; + +/** + * struct xhci_sideband_event - sideband event + * @type: notifier type + * @evt_data: event data + */ +struct xhci_sideband_event { + enum xhci_sideband_notify_type type; + void *evt_data; +}; + +/** + * struct xhci_sideband - representation of a sideband accessed usb device. + * @xhci: The xhci host controller the usb device is connected to + * @vdev: the usb device accessed via sideband + * @eps: array of endpoints controlled via sideband + * @ir: event handling and buffer for sideband accessed device + * @type: xHCI sideband type + * @mutex: mutex for sideband operations + * @intf: USB sideband client interface + * @notify_client: callback for xHCI sideband sequences + * + * FIXME usb device accessed via sideband Keeping track of sideband accessed usb devices. + */ +struct xhci_sideband { + struct xhci_hcd *xhci; + struct xhci_virt_device *vdev; + struct xhci_virt_ep *eps[EP_CTX_PER_DEV]; + struct xhci_interrupter *ir; + enum xhci_sideband_type type; + + /* Synchronizing xHCI sideband operations with client drivers operations */ + struct mutex mutex; + + struct usb_interface *intf; + int (*notify_client)(struct usb_interface *intf, + struct xhci_sideband_event *evt); +}; + +struct xhci_sideband * +xhci_sideband_register(struct usb_interface *intf, enum xhci_sideband_type type, + int (*notify_client)(struct usb_interface *intf, + struct xhci_sideband_event *evt)); +void +xhci_sideband_unregister(struct xhci_sideband *sb); +int +xhci_sideband_add_endpoint(struct xhci_sideband *sb, + struct usb_host_endpoint *host_ep); +int +xhci_sideband_remove_endpoint(struct xhci_sideband *sb, + struct usb_host_endpoint *host_ep); +int +xhci_sideband_stop_endpoint(struct xhci_sideband *sb, + struct usb_host_endpoint *host_ep); +struct sg_table * +xhci_sideband_get_endpoint_buffer(struct xhci_sideband *sb, + struct usb_host_endpoint *host_ep); +struct sg_table * +xhci_sideband_get_event_buffer(struct xhci_sideband *sb); + +#if IS_ENABLED(CONFIG_USB_XHCI_SIDEBAND) +bool xhci_sideband_check(struct usb_hcd *hcd); +#else +static inline bool xhci_sideband_check(struct usb_hcd *hcd) +{ return false; } +#endif /* IS_ENABLED(CONFIG_USB_XHCI_SIDEBAND) */ + +int +xhci_sideband_create_interrupter(struct xhci_sideband *sb, int num_seg, + bool ip_autoclear, u32 imod_interval, int intr_num); +void +xhci_sideband_remove_interrupter(struct xhci_sideband *sb); +int +xhci_sideband_interrupter_id(struct xhci_sideband *sb); + +#if IS_ENABLED(CONFIG_USB_XHCI_SIDEBAND) +void xhci_sideband_notify_ep_ring_free(struct xhci_sideband *sb, + unsigned int ep_index); +#else +static inline void xhci_sideband_notify_ep_ring_free(struct xhci_sideband *sb, + unsigned int ep_index) +{ } +#endif /* IS_ENABLED(CONFIG_USB_XHCI_SIDEBAND) */ +#endif /* __LINUX_XHCI_SIDEBAND_H */ |
