From fe8db0bbe04d31ab17dc60e205c4a3365c92e67c Mon Sep 17 00:00:00 2001 From: Abhishek Pandit-Subedi Date: Fri, 10 May 2024 20:12:42 +0000 Subject: usb: typec: Update sysfs when setting ops When adding altmode ops, update the sysfs group so that visibility is also recalculated. Reviewed-by: Heikki Krogerus Reviewed-by: Benson Leung Signed-off-by: Abhishek Pandit-Subedi Signed-off-by: Jameson Thies Reviewed-by: Dmitry Baryshkov Link: https://lore.kernel.org/r/20240510201244.2968152-3-jthies@google.com Signed-off-by: Greg Kroah-Hartman --- include/linux/usb/typec.h | 3 +++ 1 file changed, 3 insertions(+) (limited to 'include') diff --git a/include/linux/usb/typec.h b/include/linux/usb/typec.h index b35b427561ab..549275f8ac1b 100644 --- a/include/linux/usb/typec.h +++ b/include/linux/usb/typec.h @@ -167,6 +167,9 @@ struct typec_port *typec_altmode2port(struct typec_altmode *alt); void typec_altmode_update_active(struct typec_altmode *alt, bool active); +void typec_altmode_set_ops(struct typec_altmode *alt, + const struct typec_altmode_ops *ops); + enum typec_plug_index { TYPEC_PLUG_SOP_P, TYPEC_PLUG_SOP_PP, -- cgit v1.2.3 From 62ce9ef1479729b1a3f8a1b19900e28d68b3625e Mon Sep 17 00:00:00 2001 From: Marco Felsch Date: Mon, 1 Jul 2024 15:21:24 +0200 Subject: usb: typec: tcpci: add support to set connector orientation This add the support to set the optional connector orientation bit which is part of the optional CONFIG_STANDARD_OUTPUT register 0x18 [1]. This allows system designers to connect the tcpc orientation pin directly to the 2:1 ss-mux. [1] https://www.usb.org/sites/default/files/documents/usb-port_controller_specification_rev2.0_v1.0_0.pdf Signed-off-by: Marco Felsch Reviewed-by: Heikki Krogerus Link: https://lore.kernel.org/r/20240701132133.3054394-1-m.felsch@pengutronix.de Signed-off-by: Greg Kroah-Hartman --- drivers/usb/typec/tcpm/tcpci.c | 44 ++++++++++++++++++++++++++++++++++++++++++ include/linux/usb/tcpci.h | 8 ++++++++ 2 files changed, 52 insertions(+) (limited to 'include') diff --git a/drivers/usb/typec/tcpm/tcpci.c b/drivers/usb/typec/tcpm/tcpci.c index c962014bba4e..8a18d561b063 100644 --- a/drivers/usb/typec/tcpm/tcpci.c +++ b/drivers/usb/typec/tcpm/tcpci.c @@ -67,6 +67,18 @@ static int tcpci_write16(struct tcpci *tcpci, unsigned int reg, u16 val) return regmap_raw_write(tcpci->regmap, reg, &val, sizeof(u16)); } +static bool tcpci_check_std_output_cap(struct regmap *regmap, u8 mask) +{ + unsigned int reg; + int ret; + + ret = regmap_read(regmap, TCPC_STD_OUTPUT_CAP, ®); + if (ret < 0) + return ret; + + return (reg & mask) == mask; +} + static int tcpci_set_cc(struct tcpc_dev *tcpc, enum typec_cc_status cc) { struct tcpci *tcpci = tcpc_to_tcpci(tcpc); @@ -301,6 +313,28 @@ static int tcpci_set_polarity(struct tcpc_dev *tcpc, TCPC_TCPC_CTRL_ORIENTATION : 0); } +static int tcpci_set_orientation(struct tcpc_dev *tcpc, + enum typec_orientation orientation) +{ + struct tcpci *tcpci = tcpc_to_tcpci(tcpc); + unsigned int reg; + + switch (orientation) { + case TYPEC_ORIENTATION_NONE: + /* We can't put a single output into high impedance */ + fallthrough; + case TYPEC_ORIENTATION_NORMAL: + reg = TCPC_CONFIG_STD_OUTPUT_ORIENTATION_NORMAL; + break; + case TYPEC_ORIENTATION_REVERSE: + reg = TCPC_CONFIG_STD_OUTPUT_ORIENTATION_FLIPPED; + break; + } + + return regmap_update_bits(tcpci->regmap, TCPC_CONFIG_STD_OUTPUT, + TCPC_CONFIG_STD_OUTPUT_ORIENTATION_MASK, reg); +} + static void tcpci_set_partner_usb_comm_capable(struct tcpc_dev *tcpc, bool capable) { struct tcpci *tcpci = tcpc_to_tcpci(tcpc); @@ -830,6 +864,9 @@ struct tcpci *tcpci_register_port(struct device *dev, struct tcpci_data *data) if (tcpci->data->vbus_vsafe0v) tcpci->tcpc.is_vbus_vsafe0v = tcpci_is_vbus_vsafe0v; + if (tcpci->data->set_orientation) + tcpci->tcpc.set_orientation = tcpci_set_orientation; + err = tcpci_parse_config(tcpci); if (err < 0) return ERR_PTR(err); @@ -873,6 +910,13 @@ static int tcpci_probe(struct i2c_client *client) if (err < 0) return err; + err = tcpci_check_std_output_cap(chip->data.regmap, + TCPC_STD_OUTPUT_CAP_ORIENTATION); + if (err < 0) + return err; + + chip->data.set_orientation = err; + chip->tcpci = tcpci_register_port(&client->dev, &chip->data); if (IS_ERR(chip->tcpci)) return PTR_ERR(chip->tcpci); diff --git a/include/linux/usb/tcpci.h b/include/linux/usb/tcpci.h index 47a86b8a4a50..0ab39b6ea205 100644 --- a/include/linux/usb/tcpci.h +++ b/include/linux/usb/tcpci.h @@ -47,6 +47,9 @@ #define TCPC_SINK_FAST_ROLE_SWAP BIT(0) #define TCPC_CONFIG_STD_OUTPUT 0x18 +#define TCPC_CONFIG_STD_OUTPUT_ORIENTATION_MASK BIT(0) +#define TCPC_CONFIG_STD_OUTPUT_ORIENTATION_NORMAL 0 +#define TCPC_CONFIG_STD_OUTPUT_ORIENTATION_FLIPPED 1 #define TCPC_TCPC_CTRL 0x19 #define TCPC_TCPC_CTRL_ORIENTATION BIT(0) @@ -127,6 +130,7 @@ #define TCPC_DEV_CAP_2 0x26 #define TCPC_STD_INPUT_CAP 0x28 #define TCPC_STD_OUTPUT_CAP 0x29 +#define TCPC_STD_OUTPUT_CAP_ORIENTATION BIT(0) #define TCPC_MSG_HDR_INFO 0x2e #define TCPC_MSG_HDR_INFO_DATA_ROLE BIT(3) @@ -209,6 +213,9 @@ struct tcpci; * swap following Discover Identity on SOP' occurs. * Return true when the TCPM is allowed to request a Vconn swap * after Discovery Identity on SOP. + * @set_orientation: + * Optional; Enable setting the connector orientation + * CONFIG_STANDARD_OUTPUT (0x18) bit0. */ struct tcpci_data { struct regmap *regmap; @@ -216,6 +223,7 @@ struct tcpci_data { unsigned char auto_discharge_disconnect:1; unsigned char vbus_vsafe0v:1; unsigned char cable_comm_capable:1; + unsigned char set_orientation:1; int (*init)(struct tcpci *tcpci, struct tcpci_data *data); int (*set_vconn)(struct tcpci *tcpci, struct tcpci_data *data, -- cgit v1.2.3 From 2bb6b10ebe5d42c119827b57ee8123175b7ecc3d Mon Sep 17 00:00:00 2001 From: Kees Cook Date: Tue, 9 Jul 2024 08:49:56 -0700 Subject: usb: gadget: Use u16 types for 16-bit fields Since the beginning of time, struct usb_ep::maxpacket was a bitfield, and when new 16-bit members were added, the convention was followed: 1da177e4c3f41 (Linus Torvalds 2005-04-16 236) unsigned maxpacket:16; e117e742d3106 (Robert Baldyga 2013-12-13 237) unsigned maxpacket_limit:16; a59d6b91cbca5 (Tatyana Brokhman 2011-06-28 238) unsigned max_streams:16; However, there is no need for this as a simple u16 can be used instead, simplifying the struct and the resulting compiler binary output. Switch to u16 for all three, and rearrange struct slightly to minimize holes. No change in the final size of the struct results; the 2 byte gap is just moved to the end, as seen with pahole: - /* XXX 2 bytes hole, try to pack */ ... /* size: 72, cachelines: 2, members: 15 */ ... + /* padding: 2 */ Changing this simplifies future introspection[1] of maxpacket's type during allocations: drivers/usb/gadget/function/f_tcm.c:330:24: error: 'typeof' applied to a bit-field 330 | fu->cmd.buf = kmalloc(fu->ep_out->maxpacket, GFP_KERNEL); Link: https://lore.kernel.org/all/202407090928.6UaOAZAJ-lkp@intel.com [1] Signed-off-by: Kees Cook Link: https://lore.kernel.org/r/20240709154953.work.953-kees@kernel.org Signed-off-by: Greg Kroah-Hartman --- include/linux/usb/gadget.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'include') diff --git a/include/linux/usb/gadget.h b/include/linux/usb/gadget.h index 56dda8e1562d..df33333650a0 100644 --- a/include/linux/usb/gadget.h +++ b/include/linux/usb/gadget.h @@ -229,18 +229,18 @@ struct usb_ep { const char *name; const struct usb_ep_ops *ops; + const struct usb_endpoint_descriptor *desc; + const struct usb_ss_ep_comp_descriptor *comp_desc; struct list_head ep_list; struct usb_ep_caps caps; bool claimed; bool enabled; - unsigned maxpacket:16; - unsigned maxpacket_limit:16; - unsigned max_streams:16; unsigned mult:2; unsigned maxburst:5; u8 address; - const struct usb_endpoint_descriptor *desc; - const struct usb_ss_ep_comp_descriptor *comp_desc; + u16 maxpacket; + u16 maxpacket_limit; + u16 max_streams; }; /*-------------------------------------------------------------------------*/ -- cgit v1.2.3 From a5f81642a7228489292f842a106e33c558121e8b Mon Sep 17 00:00:00 2001 From: Kerem Karabay Date: Sat, 6 Jul 2024 12:03:23 +0000 Subject: USB: core: add 'shutdown' callback to usb_driver Currently there is no standardized method for USB drivers to handle shutdown events. This patch simplifies running code on shutdown for USB devices by adding a shutdown callback to usb_driver. Signed-off-by: Kerem Karabay Signed-off-by: Aditya Garg Link: https://lore.kernel.org/r/7AAC1BF4-8B60-448D-A3C1-B7E80330BE42@live.com Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/driver.c | 14 ++++++++++++++ include/linux/usb.h | 3 +++ 2 files changed, 17 insertions(+) (limited to 'include') diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c index e02ba15f6e34..b35734d03109 100644 --- a/drivers/usb/core/driver.c +++ b/drivers/usb/core/driver.c @@ -517,6 +517,19 @@ static int usb_unbind_interface(struct device *dev) return 0; } +static void usb_shutdown_interface(struct device *dev) +{ + struct usb_interface *intf = to_usb_interface(dev); + struct usb_driver *driver; + + if (!dev->driver) + return; + + driver = to_usb_driver(dev->driver); + if (driver->shutdown) + driver->shutdown(intf); +} + /** * usb_driver_claim_interface - bind a driver to an interface * @driver: the driver to be bound @@ -1059,6 +1072,7 @@ int usb_register_driver(struct usb_driver *new_driver, struct module *owner, new_driver->driver.bus = &usb_bus_type; new_driver->driver.probe = usb_probe_interface; new_driver->driver.remove = usb_unbind_interface; + new_driver->driver.shutdown = usb_shutdown_interface; new_driver->driver.owner = owner; new_driver->driver.mod_name = mod_name; new_driver->driver.dev_groups = new_driver->dev_groups; diff --git a/include/linux/usb.h b/include/linux/usb.h index 1913a13833f2..832997a9da0a 100644 --- a/include/linux/usb.h +++ b/include/linux/usb.h @@ -1171,6 +1171,7 @@ extern ssize_t usb_show_dynids(struct usb_dynids *dynids, char *buf); * post_reset method is called. * @post_reset: Called by usb_reset_device() after the device * has been reset + * @shutdown: Called at shut-down time to quiesce the device. * @id_table: USB drivers use ID table to support hotplugging. * Export this with MODULE_DEVICE_TABLE(usb,...). This must be set * or your driver's probe function will never get called. @@ -1222,6 +1223,8 @@ struct usb_driver { int (*pre_reset)(struct usb_interface *intf); int (*post_reset)(struct usb_interface *intf); + void (*shutdown)(struct usb_interface *intf); + const struct usb_device_id *id_table; const struct attribute_group **dev_groups; -- cgit v1.2.3