summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/usb/chipidea/host.c2
-rw-r--r--drivers/usb/common/common.c76
-rw-r--r--drivers/usb/common/debug.c22
-rw-r--r--drivers/usb/core/devices.c21
-rw-r--r--drivers/usb/core/endpoint.c35
-rw-r--r--drivers/usb/core/usb.c8
-rw-r--r--drivers/usb/dwc2/debugfs.c2
-rw-r--r--drivers/usb/dwc3/core.c15
-rw-r--r--drivers/usb/dwc3/core.h5
-rw-r--r--drivers/usb/dwc3/gadget.c10
-rw-r--r--drivers/usb/gadget/function/f_mass_storage.c2
-rw-r--r--drivers/usb/gadget/function/f_printer.c2
-rw-r--r--drivers/usb/gadget/udc/dummy_hcd.c2
-rw-r--r--drivers/usb/host/Makefile6
-rw-r--r--drivers/usb/host/isp116x-hcd.c7
-rw-r--r--drivers/usb/host/isp116x.h1
-rw-r--r--drivers/usb/host/isp1362-hcd.c8
-rw-r--r--drivers/usb/host/isp1362.h1
-rw-r--r--drivers/usb/host/sl811-hcd.c7
-rw-r--r--drivers/usb/host/sl811.h1
-rw-r--r--drivers/usb/host/uhci-hcd.c12
-rw-r--r--drivers/usb/host/uhci-hcd.h4
-rw-r--r--drivers/usb/host/xhci-mem.c2
-rw-r--r--drivers/usb/host/xhci-mtk-sch.c360
-rw-r--r--drivers/usb/host/xhci-mtk.c19
-rw-r--r--drivers/usb/host/xhci-mtk.h46
-rw-r--r--drivers/usb/host/xhci-ring.c1
-rw-r--r--drivers/usb/host/xhci.c30
-rw-r--r--drivers/usb/host/xhci.h8
-rw-r--r--drivers/usb/typec/Kconfig15
-rw-r--r--drivers/usb/typec/Makefile2
-rw-r--r--drivers/usb/typec/stusb160x.c4
-rw-r--r--drivers/usb/typec/tcpm/fusb302.c5
-rw-r--r--drivers/usb/typec/tcpm/tcpci.c17
-rw-r--r--drivers/usb/typec/tcpm/tcpm.c86
-rw-r--r--drivers/usb/typec/tipd/Kconfig12
-rw-r--r--drivers/usb/typec/tipd/Makefile6
-rw-r--r--drivers/usb/typec/tipd/core.c (renamed from drivers/usb/typec/tps6598x.c)68
-rw-r--r--drivers/usb/typec/tipd/tps6598x.h189
-rw-r--r--drivers/usb/typec/tipd/trace.c9
-rw-r--r--drivers/usb/typec/tipd/trace.h283
-rw-r--r--include/linux/platform_data/usb-mx2.h29
-rw-r--r--include/linux/usb.h2
-rw-r--r--include/linux/usb/ch9.h62
44 files changed, 1068 insertions, 436 deletions
diff --git a/drivers/usb/chipidea/host.c b/drivers/usb/chipidea/host.c
index 67247d2ac07a..e86d13c04bdb 100644
--- a/drivers/usb/chipidea/host.c
+++ b/drivers/usb/chipidea/host.c
@@ -32,7 +32,7 @@ struct ehci_ci_priv {
struct ci_hdrc_dma_aligned_buffer {
void *kmalloc_ptr;
void *old_xfer_buffer;
- u8 data[0];
+ u8 data[];
};
static int ehci_ci_portpower(struct usb_hcd *hcd, int portnum, bool enable)
diff --git a/drivers/usb/common/common.c b/drivers/usb/common/common.c
index fc21cf2d36f6..347fb3d3894a 100644
--- a/drivers/usb/common/common.c
+++ b/drivers/usb/common/common.c
@@ -25,6 +25,12 @@ static const char *const ep_type_names[] = {
[USB_ENDPOINT_XFER_INT] = "intr",
};
+/**
+ * usb_ep_type_string() - Returns human readable-name of the endpoint type.
+ * @ep_type: The endpoint type to return human-readable name for. If it's not
+ * any of the types: USB_ENDPOINT_XFER_{CONTROL, ISOC, BULK, INT},
+ * usually got by usb_endpoint_type(), the string 'unknown' will be returned.
+ */
const char *usb_ep_type_string(int ep_type)
{
if (ep_type < 0 || ep_type >= ARRAY_SIZE(ep_type_names))
@@ -76,6 +82,12 @@ static const char *const ssp_rate[] = {
[USB_SSP_GEN_2x2] = "super-speed-plus-gen2x2",
};
+/**
+ * usb_speed_string() - Returns human readable-name of the speed.
+ * @speed: The speed to return human-readable name for. If it's not
+ * any of the speeds defined in usb_device_speed enum, string for
+ * USB_SPEED_UNKNOWN will be returned.
+ */
const char *usb_speed_string(enum usb_device_speed speed)
{
if (speed < 0 || speed >= ARRAY_SIZE(speed_names))
@@ -84,6 +96,14 @@ const char *usb_speed_string(enum usb_device_speed speed)
}
EXPORT_SYMBOL_GPL(usb_speed_string);
+/**
+ * usb_get_maximum_speed - Get maximum requested speed for a given USB
+ * controller.
+ * @dev: Pointer to the given USB controller device
+ *
+ * The function gets the maximum speed string from property "maximum-speed",
+ * and returns the corresponding enum usb_device_speed.
+ */
enum usb_device_speed usb_get_maximum_speed(struct device *dev)
{
const char *maximum_speed;
@@ -102,6 +122,15 @@ enum usb_device_speed usb_get_maximum_speed(struct device *dev)
}
EXPORT_SYMBOL_GPL(usb_get_maximum_speed);
+/**
+ * usb_get_maximum_ssp_rate - Get the signaling rate generation and lane count
+ * of a SuperSpeed Plus capable device.
+ * @dev: Pointer to the given USB controller device
+ *
+ * If the string from "maximum-speed" property is super-speed-plus-genXxY where
+ * 'X' is the generation number and 'Y' is the number of lanes, then this
+ * function returns the corresponding enum usb_ssp_rate.
+ */
enum usb_ssp_rate usb_get_maximum_ssp_rate(struct device *dev)
{
const char *maximum_speed;
@@ -116,6 +145,12 @@ enum usb_ssp_rate usb_get_maximum_ssp_rate(struct device *dev)
}
EXPORT_SYMBOL_GPL(usb_get_maximum_ssp_rate);
+/**
+ * usb_state_string - Returns human readable name for the state.
+ * @state: The state to return a human-readable name for. If it's not
+ * any of the states devices in usb_device_state_string enum,
+ * the string UNKNOWN will be returned.
+ */
const char *usb_state_string(enum usb_device_state state)
{
static const char *const names[] = {
@@ -165,6 +200,47 @@ enum usb_dr_mode usb_get_dr_mode(struct device *dev)
}
EXPORT_SYMBOL_GPL(usb_get_dr_mode);
+/**
+ * usb_decode_interval - Decode bInterval into the time expressed in 1us unit
+ * @epd: The descriptor of the endpoint
+ * @speed: The speed that the endpoint works as
+ *
+ * Function returns the interval expressed in 1us unit for servicing
+ * endpoint for data transfers.
+ */
+unsigned int usb_decode_interval(const struct usb_endpoint_descriptor *epd,
+ enum usb_device_speed speed)
+{
+ unsigned int interval = 0;
+
+ switch (usb_endpoint_type(epd)) {
+ case USB_ENDPOINT_XFER_CONTROL:
+ /* uframes per NAK */
+ if (speed == USB_SPEED_HIGH)
+ interval = epd->bInterval;
+ break;
+ case USB_ENDPOINT_XFER_ISOC:
+ interval = 1 << (epd->bInterval - 1);
+ break;
+ case USB_ENDPOINT_XFER_BULK:
+ /* uframes per NAK */
+ if (speed == USB_SPEED_HIGH && usb_endpoint_dir_out(epd))
+ interval = epd->bInterval;
+ break;
+ case USB_ENDPOINT_XFER_INT:
+ if (speed >= USB_SPEED_HIGH)
+ interval = 1 << (epd->bInterval - 1);
+ else
+ interval = epd->bInterval;
+ break;
+ }
+
+ interval *= (speed >= USB_SPEED_HIGH) ? 125 : 1000;
+
+ return interval;
+}
+EXPORT_SYMBOL_GPL(usb_decode_interval);
+
#ifdef CONFIG_OF
/**
* of_usb_get_dr_mode_by_phy - Get dual role mode for the controller device
diff --git a/drivers/usb/common/debug.c b/drivers/usb/common/debug.c
index ba849c7bc5c7..a76a086b9c54 100644
--- a/drivers/usb/common/debug.c
+++ b/drivers/usb/common/debug.c
@@ -207,8 +207,26 @@ static void usb_decode_set_isoch_delay(__u8 wValue, char *str, size_t size)
snprintf(str, size, "Set Isochronous Delay(Delay = %d ns)", wValue);
}
-/*
- * usb_decode_ctrl - returns a string representation of ctrl request
+/**
+ * usb_decode_ctrl - Returns human readable representation of control request.
+ * @str: buffer to return a human-readable representation of control request.
+ * This buffer should have about 200 bytes.
+ * @size: size of str buffer.
+ * @bRequestType: matches the USB bmRequestType field
+ * @bRequest: matches the USB bRequest field
+ * @wValue: matches the USB wValue field (CPU byte order)
+ * @wIndex: matches the USB wIndex field (CPU byte order)
+ * @wLength: matches the USB wLength field (CPU byte order)
+ *
+ * Function returns decoded, formatted and human-readable description of
+ * control request packet.
+ *
+ * The usage scenario for this is for tracepoints, so function as a return
+ * use the same value as in parameters. This approach allows to use this
+ * function in TP_printk
+ *
+ * Important: wValue, wIndex, wLength parameters before invoking this function
+ * should be processed by le16_to_cpu macro.
*/
const char *usb_decode_ctrl(char *str, size_t size, __u8 bRequestType,
__u8 bRequest, __u16 wValue, __u16 wIndex,
diff --git a/drivers/usb/core/devices.c b/drivers/usb/core/devices.c
index 1ef2de6e375a..d8b0041de612 100644
--- a/drivers/usb/core/devices.c
+++ b/drivers/usb/core/devices.c
@@ -157,38 +157,25 @@ static char *usb_dump_endpoint_descriptor(int speed, char *start, char *end,
switch (usb_endpoint_type(desc)) {
case USB_ENDPOINT_XFER_CONTROL:
type = "Ctrl";
- if (speed == USB_SPEED_HIGH) /* uframes per NAK */
- interval = desc->bInterval;
- else
- interval = 0;
dir = 'B'; /* ctrl is bidirectional */
break;
case USB_ENDPOINT_XFER_ISOC:
type = "Isoc";
- interval = 1 << (desc->bInterval - 1);
break;
case USB_ENDPOINT_XFER_BULK:
type = "Bulk";
- if (speed == USB_SPEED_HIGH && dir == 'O') /* uframes per NAK */
- interval = desc->bInterval;
- else
- interval = 0;
break;
case USB_ENDPOINT_XFER_INT:
type = "Int.";
- if (speed == USB_SPEED_HIGH || speed >= USB_SPEED_SUPER)
- interval = 1 << (desc->bInterval - 1);
- else
- interval = desc->bInterval;
break;
default: /* "can't happen" */
return start;
}
- interval *= (speed == USB_SPEED_HIGH ||
- speed >= USB_SPEED_SUPER) ? 125 : 1000;
- if (interval % 1000)
+
+ interval = usb_decode_interval(desc, speed);
+ if (interval % 1000) {
unit = 'u';
- else {
+ } else {
unit = 'm';
interval /= 1000;
}
diff --git a/drivers/usb/core/endpoint.c b/drivers/usb/core/endpoint.c
index 903426b6d305..a2530811cf7d 100644
--- a/drivers/usb/core/endpoint.c
+++ b/drivers/usb/core/endpoint.c
@@ -84,40 +84,13 @@ static ssize_t interval_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
struct ep_device *ep = to_ep_device(dev);
+ unsigned int interval;
char unit;
- unsigned interval = 0;
- unsigned in;
- in = (ep->desc->bEndpointAddress & USB_DIR_IN);
-
- switch (usb_endpoint_type(ep->desc)) {
- case USB_ENDPOINT_XFER_CONTROL:
- if (ep->udev->speed == USB_SPEED_HIGH)
- /* uframes per NAK */
- interval = ep->desc->bInterval;
- break;
-
- case USB_ENDPOINT_XFER_ISOC:
- interval = 1 << (ep->desc->bInterval - 1);
- break;
-
- case USB_ENDPOINT_XFER_BULK:
- if (ep->udev->speed == USB_SPEED_HIGH && !in)
- /* uframes per NAK */
- interval = ep->desc->bInterval;
- break;
-
- case USB_ENDPOINT_XFER_INT:
- if (ep->udev->speed == USB_SPEED_HIGH)
- interval = 1 << (ep->desc->bInterval - 1);
- else
- interval = ep->desc->bInterval;
- break;
- }
- interval *= (ep->udev->speed == USB_SPEED_HIGH) ? 125 : 1000;
- if (interval % 1000)
+ interval = usb_decode_interval(ep->desc, ep->udev->speed);
+ if (interval % 1000) {
unit = 'u';
- else {
+ } else {
unit = 'm';
interval /= 1000;
}
diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c
index a566bb494e24..2ce3667ec6fa 100644
--- a/drivers/usb/core/usb.c
+++ b/drivers/usb/core/usb.c
@@ -982,17 +982,15 @@ static struct notifier_block usb_bus_nb = {
.notifier_call = usb_bus_notify,
};
-static struct dentry *usb_devices_root;
-
static void usb_debugfs_init(void)
{
- usb_devices_root = debugfs_create_file("devices", 0444, usb_debug_root,
- NULL, &usbfs_devices_fops);
+ debugfs_create_file("devices", 0444, usb_debug_root, NULL,
+ &usbfs_devices_fops);
}
static void usb_debugfs_cleanup(void)
{
- debugfs_remove(usb_devices_root);
+ debugfs_remove(debugfs_lookup("devices", usb_debug_root));
}
/*
diff --git a/drivers/usb/dwc2/debugfs.c b/drivers/usb/dwc2/debugfs.c
index aaafd463d72a..f13eed4231e1 100644
--- a/drivers/usb/dwc2/debugfs.c
+++ b/drivers/usb/dwc2/debugfs.c
@@ -691,6 +691,8 @@ static int params_show(struct seq_file *seq, void *v)
print_param(seq, p, ulpi_fs_ls);
print_param(seq, p, host_support_fs_ls_low_power);
print_param(seq, p, host_ls_low_power_phy_clk);
+ print_param(seq, p, activate_stm_fs_transceiver);
+ print_param(seq, p, activate_stm_id_vb_detection);
print_param(seq, p, ts_dline);
print_param(seq, p, reload_ctl);
print_param_hex(seq, p, ahbcfg);
diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
index f2448d0a9d39..94fdbe502ce9 100644
--- a/drivers/usb/dwc3/core.c
+++ b/drivers/usb/dwc3/core.c
@@ -1238,6 +1238,8 @@ static void dwc3_get_properties(struct dwc3 *dwc)
u8 rx_max_burst_prd;
u8 tx_thr_num_pkt_prd;
u8 tx_max_burst_prd;
+ const char *usb_psy_name;
+ int ret;
/* default to highest possible threshold */
lpm_nyet_threshold = 0xf;
@@ -1263,6 +1265,13 @@ static void dwc3_get_properties(struct dwc3 *dwc)
else
dwc->sysdev = dwc->dev;
+ ret = device_property_read_string(dev, "usb-psy-name", &usb_psy_name);
+ if (ret >= 0) {
+ dwc->usb_psy = power_supply_get_by_name(usb_psy_name);
+ if (!dwc->usb_psy)
+ dev_err(dev, "couldn't get usb power supply\n");
+ }
+
dwc->has_lpm_erratum = device_property_read_bool(dev,
"snps,has-lpm-erratum");
device_property_read_u8(dev, "snps,lpm-nyet-threshold",
@@ -1619,6 +1628,9 @@ disable_clks:
assert_reset:
reset_control_assert(dwc->reset);
+ if (dwc->usb_psy)
+ power_supply_put(dwc->usb_psy);
+
return ret;
}
@@ -1641,6 +1653,9 @@ static int dwc3_remove(struct platform_device *pdev)
dwc3_free_event_buffers(dwc);
dwc3_free_scratch_buffers(dwc);
+ if (dwc->usb_psy)
+ power_supply_put(dwc->usb_psy);
+
return 0;
}
diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h
index 052b20d52651..ce6bd84e2b39 100644
--- a/drivers/usb/dwc3/core.h
+++ b/drivers/usb/dwc3/core.h
@@ -30,6 +30,8 @@
#include <linux/phy/phy.h>
+#include <linux/power_supply.h>
+
#define DWC3_MSG_MAX 500
/* Global constants */
@@ -986,6 +988,7 @@ struct dwc3_scratchpad_array {
* @role_sw: usb_role_switch handle
* @role_switch_default_mode: default operation mode of controller while
* usb role is USB_ROLE_NONE.
+ * @usb_psy: pointer to power supply interface.
* @usb2_phy: pointer to USB2 PHY
* @usb3_phy: pointer to USB3 PHY
* @usb2_generic_phy: pointer to USB2 PHY
@@ -1125,6 +1128,8 @@ struct dwc3 {
struct usb_role_switch *role_sw;
enum usb_dr_mode role_switch_default_mode;
+ struct power_supply *usb_psy;
+
u32 fladj;
u32 irq_gadget;
u32 otg_irq;
diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
index aebcf8ec0716..47809835e163 100644
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -2530,11 +2530,19 @@ static void dwc3_gadget_set_ssp_rate(struct usb_gadget *g,
static int dwc3_gadget_vbus_draw(struct usb_gadget *g, unsigned int mA)
{
struct dwc3 *dwc = gadget_to_dwc(g);
+ union power_supply_propval val = {0};
+ int ret;
if (dwc->usb2_phy)
return usb_phy_set_power(dwc->usb2_phy, mA);
- return 0;
+ if (!dwc->usb_psy)
+ return -EOPNOTSUPP;
+
+ val.intval = mA;
+ ret = power_supply_set_property(dwc->usb_psy, POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT, &val);
+
+ return ret;
}
static const struct usb_gadget_ops dwc3_gadget_ops = {
diff --git a/drivers/usb/gadget/function/f_mass_storage.c b/drivers/usb/gadget/function/f_mass_storage.c
index 950c9435beec..4a4703634a2a 100644
--- a/drivers/usb/gadget/function/f_mass_storage.c
+++ b/drivers/usb/gadget/function/f_mass_storage.c
@@ -351,8 +351,6 @@ static inline struct fsg_dev *fsg_from_func(struct usb_function *f)
return container_of(f, struct fsg_dev, function);
}
-typedef void (*fsg_routine_t)(struct fsg_dev *);
-
static int exception_in_progress(struct fsg_common *common)
{
return common->state > FSG_STATE_NORMAL;
diff --git a/drivers/usb/gadget/function/f_printer.c b/drivers/usb/gadget/function/f_printer.c
index 61ce8e68f7a3..f47fdc1fa7f1 100644
--- a/drivers/usb/gadget/function/f_printer.c
+++ b/drivers/usb/gadget/function/f_printer.c
@@ -825,7 +825,7 @@ set_printer_interface(struct printer_dev *dev)
result = usb_ep_enable(dev->out_ep);
if (result != 0) {
- DBG(dev, "enable %s --> %d\n", dev->in_ep->name, result);
+ DBG(dev, "enable %s --> %d\n", dev->out_ep->name, result);
goto done;
}
diff --git a/drivers/usb/gadget/udc/dummy_hcd.c b/drivers/usb/gadget/udc/dummy_hcd.c
index 57067763b100..ce24d4f28f2a 100644
--- a/drivers/usb/gadget/udc/dummy_hcd.c
+++ b/drivers/usb/gadget/udc/dummy_hcd.c
@@ -1866,7 +1866,7 @@ restart:
/* handle control requests */
if (ep == &dum->ep[0] && ep->setup_stage) {
struct usb_ctrlrequest setup;
- int value = 1;
+ int value;
setup = *(struct usb_ctrlrequest *) urb->setup_packet;
/* paranoia, in case of stale queued data */
diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile
index 3e4d298d851f..171de4df50bd 100644
--- a/drivers/usb/host/Makefile
+++ b/drivers/usb/host/Makefile
@@ -19,9 +19,7 @@ ifneq ($(CONFIG_USB_XHCI_DBGCAP), )
xhci-hcd-y += xhci-dbgcap.o xhci-dbgtty.o
endif
-ifneq ($(CONFIG_USB_XHCI_MTK), )
- xhci-hcd-y += xhci-mtk-sch.o
-endif
+xhci-mtk-hcd-y := xhci-mtk.o xhci-mtk-sch.o
xhci-plat-hcd-y := xhci-plat.o
ifneq ($(CONFIG_USB_XHCI_MVEBU), )
@@ -73,7 +71,7 @@ obj-$(CONFIG_USB_XHCI_PCI) += xhci-pci.o
obj-$(CONFIG_USB_XHCI_PCI_RENESAS) += xhci-pci-renesas.o
obj-$(CONFIG_USB_XHCI_PLATFORM) += xhci-plat-hcd.o
obj-$(CONFIG_USB_XHCI_HISTB) += xhci-histb.o
-obj-$(CONFIG_USB_XHCI_MTK) += xhci-mtk.o
+obj-$(CONFIG_USB_XHCI_MTK) += xhci-mtk-hcd.o
obj-$(CONFIG_USB_XHCI_TEGRA) += xhci-tegra.o
obj-$(CONFIG_USB_SL811_HCD) += sl811-hcd.o
obj-$(CONFIG_USB_SL811_CS) += sl811_cs.o
diff --git a/drivers/usb/host/isp116x-hcd.c b/drivers/usb/host/isp116x-hcd.c
index 8544a2a2c1e6..8835f6bd528e 100644
--- a/drivers/usb/host/isp116x-hcd.c
+++ b/drivers/usb/host/isp116x-hcd.c
@@ -1200,14 +1200,13 @@ DEFINE_SHOW_ATTRIBUTE(isp116x_debug);
static void create_debug_file(struct isp116x *isp116x)
{
- isp116x->dentry = debugfs_create_file(hcd_name,
- S_IRUGO, NULL, isp116x,
- &isp116x_debug_fops);
+ debugfs_create_file(hcd_name, S_IRUGO, usb_debug_root, isp116x,
+ &isp116x_debug_fops);
}
static void remove_debug_file(struct isp116x *isp116x)
{
- debugfs_remove(isp116x->dentry);
+ debugfs_remove(debugfs_lookup(hcd_name, usb_debug_root));
}
#else
diff --git a/drivers/usb/host/isp116x.h b/drivers/usb/host/isp116x.h
index a5e929c10d53..84904025fe7f 100644
--- a/drivers/usb/host/isp116x.h
+++ b/drivers/usb/host/isp116x.h
@@ -260,7 +260,6 @@ struct isp116x {
struct isp116x_platform_data *board;
- struct dentry *dentry;
unsigned long stat1, stat2, stat4, stat8, stat16;
/* HC registers */
diff --git a/drivers/usb/host/isp1362-hcd.c b/drivers/usb/host/isp1362-hcd.c
index 2cecb36d241b..d8610ce8f2ec 100644
--- a/drivers/usb/host/isp1362-hcd.c
+++ b/drivers/usb/host/isp1362-hcd.c
@@ -2164,15 +2164,13 @@ DEFINE_SHOW_ATTRIBUTE(isp1362);
/* expect just one isp1362_hcd per system */
static void create_debug_file(struct isp1362_hcd *isp1362_hcd)
{
- isp1362_hcd->debug_file = debugfs_create_file("isp1362", S_IRUGO,
- usb_debug_root,
- isp1362_hcd,
- &isp1362_fops);
+ debugfs_create_file("isp1362", S_IRUGO, usb_debug_root, isp1362_hcd,
+ &isp1362_fops);
}
static void remove_debug_file(struct isp1362_hcd *isp1362_hcd)
{
- debugfs_remove(isp1362_hcd->debug_file);
+ debugfs_remove(debugfs_lookup("isp1362", usb_debug_root));
}
/*-------------------------------------------------------------------------*/
diff --git a/drivers/usb/host/isp1362.h b/drivers/usb/host/isp1362.h
index 208705b08d37..74ca4be24723 100644
--- a/drivers/usb/host/isp1362.h
+++ b/drivers/usb/host/isp1362.h
@@ -435,7 +435,6 @@ struct isp1362_hcd {
struct isp1362_platform_data *board;
- struct dentry *debug_file;
unsigned long stat1, stat2, stat4, stat8, stat16;
/* HC registers */
diff --git a/drivers/usb/host/sl811-hcd.c b/drivers/usb/host/sl811-hcd.c
index 115ced0d93e1..d49fb656d34b 100644
--- a/drivers/usb/host/sl811-hcd.c
+++ b/drivers/usb/host/sl811-hcd.c
@@ -1496,14 +1496,13 @@ DEFINE_SHOW_ATTRIBUTE(sl811h_debug);
/* expect just one sl811 per system */
static void create_debug_file(struct sl811 *sl811)
{
- sl811->debug_file = debugfs_create_file("sl811h", S_IRUGO,
- usb_debug_root, sl811,
- &sl811h_debug_fops);
+ debugfs_create_file("sl811h", S_IRUGO, usb_debug_root, sl811,
+ &sl811h_debug_fops);
}
static void remove_debug_file(struct sl811 *sl811)
{
- debugfs_remove(sl811->debug_file);
+ debugfs_remove(debugfs_lookup("sl811h", usb_debug_root));
}
/*-------------------------------------------------------------------------*/
diff --git a/drivers/usb/host/sl811.h b/drivers/usb/host/sl811.h
index 2abe51a5db44..ba8c9aa7dee8 100644
--- a/drivers/usb/host/sl811.h
+++ b/drivers/usb/host/sl811.h
@@ -123,7 +123,6 @@ struct sl811 {
void __iomem *addr_reg;
void __iomem *data_reg;
struct sl811_platform_data *board;
- struct dentry *debug_file;
unsigned long stat_insrmv;
unsigned long stat_wake;
diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c
index 03bc59755123..d90b869f5f40 100644
--- a/drivers/usb/host/uhci-hcd.c
+++ b/drivers/usb/host/uhci-hcd.c
@@ -536,7 +536,8 @@ static void release_uhci(struct uhci_hcd *uhci)
uhci->is_initialized = 0;
spin_unlock_irq(&uhci->lock);
- debugfs_remove(uhci->dentry);
+ debugfs_remove(debugfs_lookup(uhci_to_hcd(uhci)->self.bus_name,
+ uhci_debugfs_root));
for (i = 0; i < UHCI_NUM_SKELQH; i++)
uhci_free_qh(uhci, uhci->skelqh[i]);
@@ -577,7 +578,6 @@ static int uhci_start(struct usb_hcd *hcd)
struct uhci_hcd *uhci = hcd_to_uhci(hcd);
int retval = -EBUSY;
int i;
- struct dentry __maybe_unused *dentry;
hcd->uses_new_polling = 1;
/* Accept arbitrarily long scatter-gather lists */
@@ -590,10 +590,8 @@ static int uhci_start(struct usb_hcd *hcd)
init_waitqueue_head(&uhci->waitqh);
#ifdef UHCI_DEBUG_OPS
- uhci->dentry = debugfs_create_file(hcd->self.bus_name,
- S_IFREG|S_IRUGO|S_IWUSR,
- uhci_debugfs_root, uhci,
- &uhci_debug_operations);
+ debugfs_create_file(hcd->self.bus_name, S_IFREG|S_IRUGO|S_IWUSR,
+ uhci_debugfs_root, uhci, &uhci_debug_operations);
#endif
uhci->frame = dma_alloc_coherent(uhci_dev(uhci),
@@ -702,7 +700,7 @@ err_alloc_frame_cpu:
uhci->frame, uhci->frame_dma_handle);
err_alloc_frame:
- debugfs_remove(uhci->dentry);
+ debugfs_remove(debugfs_lookup(hcd->self.bus_name, uhci_debugfs_root));
return retval;
}
diff --git a/drivers/usb/host/uhci-hcd.h b/drivers/usb/host/uhci-hcd.h
index 7f9f33c8c232..8ae5ccd26753 100644
--- a/drivers/usb/host/uhci-hcd.h
+++ b/drivers/usb/host/uhci-hcd.h
@@ -381,10 +381,6 @@ enum uhci_rh_state {
* The full UHCI controller information:
*/
struct uhci_hcd {
-
- /* debugfs */
- struct dentry *dentry;
-
/* Grabbed from PCI */
unsigned long io_addr;
diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c
index f2c4ee7c4786..7eb8c07c8418 100644
--- a/drivers/usb/host/xhci-mem.c
+++ b/drivers/usb/host/xhci-mem.c
@@ -532,7 +532,7 @@ struct xhci_ep_ctx *xhci_get_ep_ctx(struct xhci_hcd *xhci,
return (struct xhci_ep_ctx *)
(ctx->bytes + (ep_index * CTX_SIZE(xhci->hcc_params)));
}
-
+EXPORT_SYMBOL_GPL(xhci_get_ep_ctx);
/***************** Streams structures manipulation *************************/
diff --git a/drivers/usb/host/xhci-mtk-sch.c b/drivers/usb/host/xhci-mtk-sch.c
index b45e5bf08997..a59d1f6d4744 100644
--- a/drivers/usb/host/xhci-mtk-sch.c
+++ b/drivers/usb/host/xhci-mtk-sch.c
@@ -25,6 +25,15 @@
*/
#define TT_MICROFRAMES_MAX 9
+#define DBG_BUF_EN 64
+
+/* schedule error type */
+#define ESCH_SS_Y6 1001
+#define ESCH_SS_OVERLAP 1002
+#define ESCH_CS_OVERFLOW 1003
+#define ESCH_BW_OVERFLOW 1004
+#define ESCH_FIXME 1005
+
/* mtk scheduler bitmasks */
#define EP_BPKTS(p) ((p) & 0x7f)
#define EP_BCSCOUNT(p) (((p) & 0x7) << 8)
@@ -32,13 +41,75 @@
#define EP_BOFFSET(p) ((p) & 0x3fff)
#define EP_BREPEAT(p) (((p) & 0x7fff) << 16)
+static char *sch_error_string(int err_num)
+{
+ switch (err_num) {
+ case ESCH_SS_Y6:
+ return "Can't schedule Start-Split in Y6";
+ case ESCH_SS_OVERLAP:
+ return "Can't find a suitable Start-Split location";
+ case ESCH_CS_OVERFLOW:
+ return "The last Complete-Split is greater than 7";
+ case ESCH_BW_OVERFLOW:
+ return "Bandwidth exceeds the maximum limit";
+ case ESCH_FIXME:
+ return "FIXME, to be resolved";
+ default:
+ return "Unknown";
+ }
+}
+
static int is_fs_or_ls(enum usb_device_speed speed)
{
return speed == USB_SPEED_FULL || speed == USB_SPEED_LOW;
}
+static const char *
+decode_ep(struct usb_host_endpoint *ep, enum usb_device_speed speed)
+{
+ static char buf[DBG_BUF_EN];
+ struct usb_endpoint_descriptor *epd = &ep->desc;
+ unsigned int interval;
+ const char *unit;
+
+ interval = usb_decode_interval(epd, speed);
+ if (interval % 1000) {
+ unit = "us";
+ } else {
+ unit = "ms";
+ interval /= 1000;
+ }
+
+ snprintf(buf, DBG_BUF_EN, "%s ep%d%s %s, mpkt:%d, interval:%d/%d%s\n",
+ usb_speed_string(speed), usb_endpoint_num(epd),
+ usb_endpoint_dir_in(epd) ? "in" : "out",
+ usb_ep_type_string(usb_endpoint_type(epd)),
+ usb_endpoint_maxp(epd), epd->bInterval, interval, unit);
+
+ return buf;
+}
+
+static u32 get_bw_boundary(enum usb_device_speed speed)
+{
+ u32 boundary;
+
+ switch (speed) {
+ case USB_SPEED_SUPER_PLUS:
+ boundary = SSP_BW_BOUNDARY;
+ break;
+ case USB_SPEED_SUPER:
+ boundary = SS_BW_BOUNDARY;
+ break;
+ default:
+ boundary = HS_BW_BOUNDARY;
+ break;
+ }
+
+ return boundary;
+}
+
/*
-* get the index of bandwidth domains array which @ep belongs to.
+* get the bandwidth domain which @ep belongs to.
*
* the bandwidth domain array is saved to @sch_array of struct xhci_hcd_mtk,
* each HS root port is treated as a single bandwidth domain,
@@ -49,9 +120,11 @@ static int is_fs_or_ls(enum usb_device_speed speed)
* so the bandwidth domain array is organized as follow for simplification:
* SSport0-OUT, SSport0-IN, ..., SSportX-OUT, SSportX-IN, HSport0, ..., HSportY
*/
-static int get_bw_index(struct xhci_hcd *xhci, struct usb_device *udev,
- struct usb_host_endpoint *ep)
+static struct mu3h_sch_bw_info *
+get_bw_info(struct xhci_hcd_mtk *mtk, struct usb_device *udev,
+ struct usb_host_endpoint *ep)
{
+ struct xhci_hcd *xhci = hcd_to_xhci(mtk->hcd);
struct xhci_virt_device *virt_dev;
int bw_index;
@@ -67,7 +140,7 @@ static int get_bw_index(struct xhci_hcd *xhci, struct usb_device *udev,
bw_index = virt_dev->real_port + xhci->usb3_rhub.num_ports - 1;
}
- return bw_index;
+ return &mtk->sch_array[bw_index];
}
static u32 get_esit(struct xhci_ep_ctx *ep_ctx)
@@ -85,7 +158,6 @@ static struct mu3h_sch_tt *find_tt(struct usb_device *udev)
{
struct usb_tt *utt = udev->tt;
struct mu3h_sch_tt *tt, **tt_index, **ptt;
- unsigned int port;
bool allocated_index = false;
if (!utt)
@@ -107,10 +179,8 @@ static struct mu3h_sch_tt *find_tt(struct usb_device *udev)
utt->hcpriv = tt_index;
allocated_index = true;
}
- port = udev->ttport - 1;
- ptt = &tt_index[port];
+ ptt = &tt_index[udev->ttport - 1];
} else {
- port = 0;
ptt = (struct mu3h_sch_tt **) &utt->hcpriv;
}
@@ -125,8 +195,6 @@ static struct mu3h_sch_tt *find_tt(struct usb_device *udev)
return ERR_PTR(-ENOMEM);
}
INIT_LIST_HEAD(&tt->ep_list);
- tt->usb_tt = utt;
- tt->tt_port = port;
*ptt = tt;
}
@@ -200,14 +268,15 @@ static struct mu3h_sch_ep_info *create_sch_ep(struct usb_device *udev,
sch_ep->sch_tt = tt;
sch_ep->ep = ep;
+ sch_ep->speed = udev->speed;
INIT_LIST_HEAD(&sch_ep->endpoint);
INIT_LIST_HEAD(&sch_ep->tt_endpoint);
return sch_ep;
}
-static void setup_sch_info(struct usb_device *udev,
- struct xhci_ep_ctx *ep_ctx, struct mu3h_sch_ep_info *sch_ep)
+static void setup_sch_info(struct xhci_ep_ctx *ep_ctx,
+ struct mu3h_sch_ep_info *sch_ep)
{
u32 ep_type;
u32 maxpkt;
@@ -234,7 +303,7 @@ static void setup_sch_info(struct usb_device *udev,
sch_ep->burst_mode = 0;
sch_ep->repeat = 0;
- if (udev->speed == USB_SPEED_HIGH) {
+ if (sch_ep->speed == USB_SPEED_HIGH) {
sch_ep->cs_count = 0;
/*
@@ -252,7 +321,7 @@ static void setup_sch_info(struct usb_device *udev,
sch_ep->pkts = max_burst + 1;
sch_ep->bw_cost_per_microframe = maxpkt * sch_ep->pkts;
bwb_table[0] = sch_ep->bw_cost_per_microframe;
- } else if (udev->speed >= USB_SPEED_SUPER) {
+ } else if (sch_ep->speed >= USB_SPEED_SUPER) {
/* usb3_r1 spec section4.4.7 & 4.4.8 */
sch_ep->cs_count = 0;
sch_ep->burst_mode = 1;
@@ -297,7 +366,7 @@ static void setup_sch_info(struct usb_device *udev,
/* last one <= bw_cost_per_microframe */
bwb_table[i] = remainder;
}
- } else if (is_fs_or_ls(udev->speed)) {
+ } else if (is_fs_or_ls(sch_ep->speed)) {
sch_ep->pkts = 1; /* at most one packet for each microframe */
/*
@@ -375,21 +444,42 @@ static void update_bus_bw(struct mu3h_sch_bw_info *sch_bw,
sch_ep->bw_budget_table[j];
}
}
- sch_ep->allocated = used;
}
-static int check_sch_tt(struct usb_device *udev,
- struct mu3h_sch_ep_info *sch_ep, u32 offset)
+static int check_fs_bus_bw(struct mu3h_sch_ep_info *sch_ep, int offset)
+{
+ struct mu3h_sch_tt *tt = sch_ep->sch_tt;
+ u32 num_esit, tmp;
+ int base;
+ int i, j;
+
+ num_esit = XHCI_MTK_MAX_ESIT / sch_ep->esit;
+ for (i = 0; i < num_esit; i++) {
+ base = offset + i * sch_ep->esit;
+
+ /*
+ * Compared with hs bus, no matter what ep type,
+ * the hub will always delay one uframe to send data
+ */
+ for (j = 0; j < sch_ep->cs_count; j++) {
+ tmp = tt->fs_bus_bw[base + j] + sch_ep->bw_cost_per_microframe;
+ if (tmp > FS_PAYLOAD_MAX)
+ return -ESCH_BW_OVERFLOW;
+ }
+ }
+
+ return 0;
+}
+
+static int check_sch_tt(struct mu3h_sch_ep_info *sch_ep, u32 offset)
{
struct mu3h_sch_tt *tt = sch_ep->sch_tt;
u32 extra_cs_count;
- u32 fs_budget_start;
u32 start_ss, last_ss;
u32 start_cs, last_cs;
int i;
start_ss = offset % 8;
- fs_budget_start = (start_ss + 1) % 8;
if (sch_ep->ep_type == ISOC_OUT_EP) {
last_ss = start_ss + sch_ep->cs_count - 1;
@@ -399,11 +489,11 @@ static int check_sch_tt(struct usb_device *udev,
* must never schedule Start-Split in Y6
*/
if (!(start_ss == 7 || last_ss < 6))
- return -ERANGE;
+ return -ESCH_SS_Y6;
for (i = 0; i < sch_ep->cs_count; i++)
- if (test_bit(offset + i, tt->split_bit_map))
- return -ERANGE;
+ if (test_bit(offset + i, tt->ss_bit_map))
+ return -ESCH_SS_OVERLAP;
} else {
u32 cs_count = DIV_ROUND_UP(sch_ep->maxpkt, FS_PAYLOAD_MAX);
@@ -413,28 +503,26 @@ static int check_sch_tt(struct usb_device *udev,
* must never schedule Start-Split in Y6
*/
if (start_ss == 6)
- return -ERANGE;
+ return -ESCH_SS_Y6;
/* one uframe for ss + one uframe for idle */
start_cs = (start_ss + 2) % 8;
last_cs = start_cs + cs_count - 1;
if (last_cs > 7)
- return -ERANGE;
+ return -ESCH_CS_OVERFLOW;
if (sch_ep->ep_type == ISOC_IN_EP)
extra_cs_count = (last_cs == 7) ? 1 : 2;
else /* ep_type : INTR IN / INTR OUT */
- extra_cs_count = (fs_budget_start == 6) ? 1 : 2;
+ extra_cs_count = 1;
cs_count += extra_cs_count;
if (cs_count > 7)
cs_count = 7; /* HW limit */
- for (i = 0; i < cs_count + 2; i++) {
- if (test_bit(offset + i, tt->split_bit_map))
- return -ERANGE;
- }
+ if (test_bit(offset, tt->ss_bit_map))
+ return -ESCH_SS_OVERLAP;
sch_ep->cs_count = cs_count;
/* one for ss, the other for idle */
@@ -448,41 +536,85 @@ static int check_sch_tt(struct usb_device *udev,
sch_ep->num_budget_microframes = sch_ep->esit;
}
- return 0;
+ return check_fs_bus_bw(sch_ep, offset);
}
-static void update_sch_tt(struct usb_device *udev,
- struct mu3h_sch_ep_info *sch_ep)
+static void update_sch_tt(struct mu3h_sch_ep_info *sch_ep, bool used)
{
struct mu3h_sch_tt *tt = sch_ep->sch_tt;
u32 base, num_esit;
+ int bw_updated;
+ int bits;
int i, j;
num_esit = XHCI_MTK_MAX_ESIT / sch_ep->esit;
+ bits = (sch_ep->ep_type == ISOC_OUT_EP) ? sch_ep->cs_count : 1;
+
+ if (used)
+ bw_updated = sch_ep->bw_cost_per_microframe;
+ else
+ bw_updated = -sch_ep->bw_cost_per_microframe;
+
for (i = 0; i < num_esit; i++) {
base = sch_ep->offset + i * sch_ep->esit;
- for (j = 0; j < sch_ep->num_budget_microframes; j++)
- set_bit(base + j, tt->split_bit_map);
+
+ for (j = 0; j < bits; j++) {
+ if (used)
+ set_bit(base + j, tt->ss_bit_map);
+ else
+ clear_bit(base + j, tt->ss_bit_map);
+ }
+
+ for (j = 0; j < sch_ep->cs_count; j++)
+ tt->fs_bus_bw[base + j] += bw_updated;
}
- list_add_tail(&sch_ep->tt_endpoint, &tt->ep_list);
+ if (used)
+ list_add_tail(&sch_ep->tt_endpoint, &tt->ep_list);
+ else
+ list_del(&sch_ep->tt_endpoint);
}
-static int check_sch_bw(struct usb_device *udev,
- struct mu3h_sch_bw_info *sch_bw, struct mu3h_sch_ep_info *sch_ep)
+static int load_ep_bw(struct mu3h_sch_bw_info *sch_bw,
+ struct mu3h_sch_ep_info *sch_ep, bool loaded)
+{
+ if (sch_ep->sch_tt)
+ update_sch_tt(sch_ep, loaded);
+
+ /* update bus bandwidth info */
+ update_bus_bw(sch_bw, sch_ep, loaded);
+ sch_ep->allocated = loaded;
+
+ return 0;
+}
+
+static u32 get_esit_boundary(struct mu3h_sch_ep_info *sch_ep)
+{
+ u32 boundary = sch_ep->esit;
+
+ if (sch_ep->sch_tt) { /* LS/FS with TT */
+ /* tune for CS */
+ if (sch_ep->ep_type != ISOC_OUT_EP)
+ boundary++;
+ else if (boundary > 1) /* normally esit >= 8 for FS/LS */
+ boundary--;
+ }
+
+ return boundary;
+}
+
+static int check_sch_bw(struct mu3h_sch_bw_info *sch_bw,
+ struct mu3h_sch_ep_info *sch_ep)
{
u32 offset;
- u32 esit;
u32 min_bw;
u32 min_index;
u32 worst_bw;
u32 bw_boundary;
+ u32 esit_boundary;
u32 min_num_budget;
u32 min_cs_count;
- bool tt_offset_ok = false;
- int ret;
-
- esit = sch_ep->esit;
+ int ret = 0;
/*
* Search through all possible schedule microframes.
@@ -492,16 +624,15 @@ static int check_sch_bw(struct usb_device *udev,
min_index = 0;
min_cs_count = sch_ep->cs_count;
min_num_budget = sch_ep->num_budget_microframes;
- for (offset = 0; offset < esit; offset++) {
- if (is_fs_or_ls(udev->speed)) {
- ret = check_sch_tt(udev, sch_ep, offset);
+ esit_boundary = get_esit_boundary(sch_ep);
+ for (offset = 0; offset < sch_ep->esit; offset++) {
+ if (sch_ep->sch_tt) {
+ ret = check_sch_tt(sch_ep, offset);
if (ret)
continue;
- else
- tt_offset_ok = true;
}
- if ((offset + sch_ep->num_budget_microframes) > sch_ep->esit)
+ if ((offset + sch_ep->num_budget_microframes) > esit_boundary)
break;
worst_bw = get_max_bw(sch_bw, sch_ep, offset);
@@ -515,33 +646,16 @@ static int check_sch_bw(struct usb_device *udev,
break;
}
- if (udev->speed == USB_SPEED_SUPER_PLUS)
- bw_boundary = SSP_BW_BOUNDARY;
- else if (udev->speed == USB_SPEED_SUPER)
- bw_boundary = SS_BW_BOUNDARY;
- else
- bw_boundary = HS_BW_BOUNDARY;
-
+ bw_boundary = get_bw_boundary(sch_ep->speed);
/* check bandwidth */
if (min_bw > bw_boundary)
- return -ERANGE;
+ return ret ? ret : -ESCH_BW_OVERFLOW;
sch_ep->offset = min_index;
sch_ep->cs_count = min_cs_count;
sch_ep->num_budget_microframes = min_num_budget;
- if (is_fs_or_ls(udev->speed)) {
- /* all offset for tt is not ok*/
- if (!tt_offset_ok)
- return -ERANGE;
-
- update_sch_tt(udev, sch_ep);
- }
-
- /* update bus bandwidth info */
- update_bus_bw(sch_bw, sch_ep, 1);
-
- return 0;
+ return load_ep_bw(sch_bw, sch_ep, true);
}
static void destroy_sch_ep(struct usb_device *udev,
@@ -549,14 +663,12 @@ static void destroy_sch_ep(struct usb_device *udev,
{
/* only release ep bw check passed by check_sch_bw() */
if (sch_ep->allocated)
- update_bus_bw(sch_bw, sch_ep, 0);
-
- list_del(&sch_ep->endpoint);
+ load_ep_bw(sch_bw, sch_ep, false);
- if (sch_ep->sch_tt) {
- list_del(&sch_ep->tt_endpoint);
+ if (sch_ep->sch_tt)
drop_tt(udev);
- }
+
+ list_del(&sch_ep->endpoint);
kfree(sch_ep);
}
@@ -606,44 +718,36 @@ int xhci_mtk_sch_init(struct xhci_hcd_mtk *mtk)
return 0;
}
-EXPORT_SYMBOL_GPL(xhci_mtk_sch_init);
void xhci_mtk_sch_exit(struct xhci_hcd_mtk *mtk)
{
kfree(mtk->sch_array);
}
-EXPORT_SYMBOL_GPL(xhci_mtk_sch_exit);
-int xhci_mtk_add_ep_quirk(struct usb_hcd *hcd, struct usb_device *udev,
- struct usb_host_endpoint *ep)
+static int add_ep_quirk(struct usb_hcd *hcd, struct usb_device *udev,
+ struct usb_host_endpoint *ep)
{
struct xhci_hcd_mtk *mtk = hcd_to_mtk(hcd);
- struct xhci_hcd *xhci;
+ struct xhci_hcd *xhci = hcd_to_xhci(hcd);
struct xhci_ep_ctx *ep_ctx;
- struct xhci_slot_ctx *slot_ctx;
struct xhci_virt_device *virt_dev;
struct mu3h_sch_ep_info *sch_ep;
unsigned int ep_index;
- xhci = hcd_to_xhci(hcd);
virt_dev = xhci->devs[udev->slot_id];
ep_index = xhci_get_endpoint_index(&ep->desc);
- slot_ctx = xhci_get_slot_ctx(xhci, virt_dev->in_ctx);
ep_ctx = xhci_get_ep_ctx(xhci, virt_dev->in_ctx, ep_index);
- xhci_dbg(xhci, "%s() type:%d, speed:%d, mpkt:%d, dir:%d, ep:%p\n",
- __func__, usb_endpoint_type(&ep->desc), udev->speed,
- usb_endpoint_maxp(&ep->desc),
- usb_endpoint_dir_in(&ep->desc), ep);
+ xhci_dbg(xhci, "%s %s\n", __func__, decode_ep(ep, udev->speed));
- if (!need_bw_sch(ep, udev->speed, slot_ctx->tt_info & TT_SLOT)) {
+ if (!need_bw_sch(ep, udev->speed, !!virt_dev->tt_info)) {
/*
* set @bpkts to 1 if it is LS or FS periodic endpoint, and its
* device does not connected through an external HS hub
*/
if (usb_endpoint_xfer_int(&ep->desc)
|| usb_endpoint_xfer_isoc(&ep->desc))
- ep_ctx->reserved[0] |= cpu_to_le32(EP_BPKTS(1));
+ ep_ctx->reserved[0] = cpu_to_le32(EP_BPKTS(1));
return 0;
}
@@ -652,41 +756,30 @@ int xhci_mtk_add_ep_quirk(struct usb_hcd *hcd, struct usb_device *udev,
if (IS_ERR_OR_NULL(sch_ep))
return -ENOMEM;
- setup_sch_info(udev, ep_ctx, sch_ep);
+ setup_sch_info(ep_ctx, sch_ep);
list_add_tail(&sch_ep->endpoint, &mtk->bw_ep_chk_list);
return 0;
}
-EXPORT_SYMBOL_GPL(xhci_mtk_add_ep_quirk);
-void xhci_mtk_drop_ep_quirk(struct usb_hcd *hcd, struct usb_device *udev,
- struct usb_host_endpoint *ep)
+static void drop_ep_quirk(struct usb_hcd *hcd, struct usb_device *udev,
+ struct usb_host_endpoint *ep)
{
struct xhci_hcd_mtk *mtk = hcd_to_mtk(hcd);
- struct xhci_hcd *xhci;
- struct xhci_slot_ctx *slot_ctx;
+ struct xhci_hcd *xhci = hcd_to_xhci(hcd);
struct xhci_virt_device *virt_dev;
- struct mu3h_sch_bw_info *sch_array;
struct mu3h_sch_bw_info *sch_bw;
struct mu3h_sch_ep_info *sch_ep, *tmp;
- int bw_index;
- xhci = hcd_to_xhci(hcd);
virt_dev = xhci->devs[udev->slot_id];
- slot_ctx = xhci_get_slot_ctx(xhci, virt_dev->in_ctx);
- sch_array = mtk->sch_array;
- xhci_dbg(xhci, "%s() type:%d, speed:%d, mpks:%d, dir:%d, ep:%p\n",
- __func__, usb_endpoint_type(&ep->desc), udev->speed,
- usb_endpoint_maxp(&ep->desc),
- usb_endpoint_dir_in(&ep->desc), ep);
+ xhci_dbg(xhci, "%s %s\n", __func__, decode_ep(ep, udev->speed));
- if (!need_bw_sch(ep, udev->speed, slot_ctx->tt_info & TT_SLOT))
+ if (!need_bw_sch(ep, udev->speed, !!virt_dev->tt_info))
return;
- bw_index = get_bw_index(xhci, udev, ep);
- sch_bw = &sch_array[bw_index];
+ sch_bw = get_bw_info(mtk, udev, ep);
list_for_each_entry_safe(sch_ep, tmp, &sch_bw->bw_ep_list, endpoint) {
if (sch_ep->ep == ep) {
@@ -695,7 +788,6 @@ void xhci_mtk_drop_ep_quirk(struct usb_hcd *hcd, struct usb_device *udev,
}
}
}
-EXPORT_SYMBOL_GPL(xhci_mtk_drop_ep_quirk);
int xhci_mtk_check_bandwidth(struct usb_hcd *hcd, struct usb_device *udev)
{
@@ -704,17 +796,17 @@ int xhci_mtk_check_bandwidth(struct usb_hcd *hcd, struct usb_device *udev)
struct xhci_virt_device *virt_dev = xhci->devs[udev->slot_id];
struct mu3h_sch_bw_info *sch_bw;
struct mu3h_sch_ep_info *sch_ep, *tmp;
- int bw_index, ret;
+ int ret;
xhci_dbg(xhci, "%s() udev %s\n", __func__, dev_name(&udev->dev));
list_for_each_entry(sch_ep, &mtk->bw_ep_chk_list, endpoint) {
- bw_index = get_bw_index(xhci, udev, sch_ep->ep);
- sch_bw = &mtk->sch_array[bw_index];
+ sch_bw = get_bw_info(mtk, udev, sch_ep->ep);
- ret = check_sch_bw(udev, sch_bw, sch_ep);
+ ret = check_sch_bw(sch_bw, sch_ep);
if (ret) {
- xhci_err(xhci, "Not enough bandwidth!\n");
+ xhci_err(xhci, "Not enough bandwidth! (%s)\n",
+ sch_error_string(-ret));
return -ENOSPC;
}
}
@@ -724,16 +816,14 @@ int xhci_mtk_check_bandwidth(struct usb_hcd *hcd, struct usb_device *udev)
struct usb_host_endpoint *ep = sch_ep->ep;
unsigned int ep_index = xhci_get_endpoint_index(&ep->desc);
- bw_index = get_bw_index(xhci, udev, ep);
- sch_bw = &mtk->sch_array[bw_index];
-
+ sch_bw = get_bw_info(mtk, udev, ep);
list_move_tail(&sch_ep->endpoint, &sch_bw->bw_ep_list);
ep_ctx = xhci_get_ep_ctx(xhci, virt_dev->in_ctx, ep_index);
- ep_ctx->reserved[0] |= cpu_to_le32(EP_BPKTS(sch_ep->pkts)
+ ep_ctx->reserved[0] = cpu_to_le32(EP_BPKTS(sch_ep->pkts)
| EP_BCSCOUNT(sch_ep->cs_count)
| EP_BBM(sch_ep->burst_mode));
- ep_ctx->reserved[1] |= cpu_to_le32(EP_BOFFSET(sch_ep->offset)
+ ep_ctx->reserved[1] = cpu_to_le32(EP_BOFFSET(sch_ep->offset)
| EP_BREPEAT(sch_ep->repeat));
xhci_dbg(xhci, " PKTS:%x, CSCOUNT:%x, BM:%x, OFFSET:%x, REPEAT:%x\n",
@@ -743,7 +833,6 @@ int xhci_mtk_check_bandwidth(struct usb_hcd *hcd, struct usb_device *udev)
return xhci_check_bandwidth(hcd, udev);
}
-EXPORT_SYMBOL_GPL(xhci_mtk_check_bandwidth);
void xhci_mtk_reset_bandwidth(struct usb_hcd *hcd, struct usb_device *udev)
{
@@ -751,16 +840,41 @@ void xhci_mtk_reset_bandwidth(struct usb_hcd *hcd, struct usb_device *udev)
struct xhci_hcd *xhci = hcd_to_xhci(hcd);
struct mu3h_sch_bw_info *sch_bw;
struct mu3h_sch_ep_info *sch_ep, *tmp;
- int bw_index;
xhci_dbg(xhci, "%s() udev %s\n", __func__, dev_name(&udev->dev));
list_for_each_entry_safe(sch_ep, tmp, &mtk->bw_ep_chk_list, endpoint) {
- bw_index = get_bw_index(xhci, udev, sch_ep->ep);
- sch_bw = &mtk->sch_array[bw_index];
+ sch_bw = get_bw_info(mtk, udev, sch_ep->ep);
destroy_sch_ep(udev, sch_bw, sch_ep);
}
xhci_reset_bandwidth(hcd, udev);
}
-EXPORT_SYMBOL_GPL(xhci_mtk_reset_bandwidth);
+
+int xhci_mtk_add_ep(struct usb_hcd *hcd, struct usb_device *udev,
+ struct usb_host_endpoint *ep)
+{
+ int ret;
+
+ ret = xhci_add_endpoint(hcd, udev, ep);
+ if (ret)
+ return ret;
+
+ if (ep->hcpriv)
+ ret = add_ep_quirk(hcd, udev, ep);
+
+ return ret;
+}
+
+int xhci_mtk_drop_ep(struct usb_hcd *hcd, struct usb_device *udev,
+ struct usb_host_endpoint *ep)
+{
+ int ret;
+
+ ret = xhci_drop_endpoint(hcd, udev, ep);
+ if (ret)
+ return ret;
+
+ drop_ep_quirk(hcd, udev, ep);
+ return 0;
+}
diff --git a/drivers/usb/host/xhci-mtk.c b/drivers/usb/host/xhci-mtk.c
index fe010cc61f19..57bcfdfa0465 100644
--- a/drivers/usb/host/xhci-mtk.c
+++ b/drivers/usb/host/xhci-mtk.c
@@ -344,15 +344,6 @@ static void usb_wakeup_set(struct xhci_hcd_mtk *mtk, bool enable)
usb_wakeup_ip_sleep_set(mtk, enable);
}
-static int xhci_mtk_setup(struct usb_hcd *hcd);
-static const struct xhci_driver_overrides xhci_mtk_overrides __initconst = {
- .reset = xhci_mtk_setup,
- .check_bandwidth = xhci_mtk_check_bandwidth,
- .reset_bandwidth = xhci_mtk_reset_bandwidth,
-};
-
-static struct hc_driver __read_mostly xhci_mtk_hc_driver;
-
static int xhci_mtk_ldos_enable(struct xhci_hcd_mtk *mtk)
{
int ret;
@@ -424,6 +415,16 @@ static int xhci_mtk_setup(struct usb_hcd *hcd)
return ret;
}
+static const struct xhci_driver_overrides xhci_mtk_overrides __initconst = {
+ .reset = xhci_mtk_setup,
+ .add_endpoint = xhci_mtk_add_ep,
+ .drop_endpoint = xhci_mtk_drop_ep,
+ .check_bandwidth = xhci_mtk_check_bandwidth,
+ .reset_bandwidth = xhci_mtk_reset_bandwidth,
+};
+
+static struct hc_driver __read_mostly xhci_mtk_hc_driver;
+
static int xhci_mtk_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
diff --git a/drivers/usb/host/xhci-mtk.h b/drivers/usb/host/xhci-mtk.h
index cbb09dfea62e..621ec1a85009 100644
--- a/drivers/usb/host/xhci-mtk.h
+++ b/drivers/usb/host/xhci-mtk.h
@@ -20,16 +20,14 @@
#define XHCI_MTK_MAX_ESIT 64
/**
- * @split_bit_map: used to avoid split microframes overlay
+ * @ss_bit_map: used to avoid start split microframes overlay
+ * @fs_bus_bw: array to keep track of bandwidth already used for FS
* @ep_list: Endpoints using this TT
- * @usb_tt: usb TT related
- * @tt_port: TT port number
*/
struct mu3h_sch_tt {
- DECLARE_BITMAP(split_bit_map, XHCI_MTK_MAX_ESIT);
+ DECLARE_BITMAP(ss_bit_map, XHCI_MTK_MAX_ESIT);
+ u32 fs_bus_bw[XHCI_MTK_MAX_ESIT];
struct list_head ep_list;
- struct usb_tt *usb_tt;
- int tt_port;
};
/**
@@ -86,7 +84,8 @@ struct mu3h_sch_ep_info {
struct mu3h_sch_tt *sch_tt;
u32 ep_type;
u32 maxpkt;
- void *ep;
+ struct usb_host_endpoint *ep;
+ enum usb_device_speed speed;
bool allocated;
/*
* mtk xHCI scheduling information put into reserved DWs
@@ -162,38 +161,13 @@ static inline struct xhci_hcd_mtk *hcd_to_mtk(struct usb_hcd *hcd)
return dev_get_drvdata(hcd->self.controller);
}
-#if IS_ENABLED(CONFIG_USB_XHCI_MTK)
int xhci_mtk_sch_init(struct xhci_hcd_mtk *mtk);
void xhci_mtk_sch_exit(struct xhci_hcd_mtk *mtk);
-int xhci_mtk_add_ep_quirk(struct usb_hcd *hcd, struct usb_device *udev,
- struct usb_host_endpoint *ep);
-void xhci_mtk_drop_ep_quirk(struct usb_hcd *hcd, struct usb_device *udev,
- struct usb_host_endpoint *ep);
+int xhci_mtk_add_ep(struct usb_hcd *hcd, struct usb_device *udev,
+ struct usb_host_endpoint *ep);
+int xhci_mtk_drop_ep(struct usb_hcd *hcd, struct usb_device *udev,
+ struct usb_host_endpoint *ep);
int xhci_mtk_check_bandwidth(struct usb_hcd *hcd, struct usb_device *udev);
void xhci_mtk_reset_bandwidth(struct usb_hcd *hcd, struct usb_device *udev);
-#else
-static inline int xhci_mtk_add_ep_quirk(struct usb_hcd *hcd,
- struct usb_device *udev, struct usb_host_endpoint *ep)
-{
- return 0;
-}
-
-static inline void xhci_mtk_drop_ep_quirk(struct usb_hcd *hcd,
- struct usb_device *udev, struct usb_host_endpoint *ep)
-{
-}
-
-static inline int xhci_mtk_check_bandwidth(struct usb_hcd *hcd,
- struct usb_device *udev)
-{
- return 0;
-}
-
-static inline void xhci_mtk_reset_bandwidth(struct usb_hcd *hcd,
- struct usb_device *udev)
-{
-}
-#endif
-
#endif /* _XHCI_MTK_H_ */
diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
index ce38076901e2..65dba0fba605 100644
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -57,7 +57,6 @@
#include <linux/dma-mapping.h>
#include "xhci.h"
#include "xhci-trace.h"
-#include "xhci-mtk.h"
static int queue_command(struct xhci_hcd *xhci, struct xhci_command *cmd,
u32 field1, u32 field2,
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
index 1975016f46bf..fab08e3d8a7d 100644
--- a/drivers/usb/host/xhci.c
+++ b/drivers/usb/host/xhci.c
@@ -20,7 +20,6 @@
#include "xhci.h"
#include "xhci-trace.h"
-#include "xhci-mtk.h"
#include "xhci-debugfs.h"
#include "xhci-dbgcap.h"
@@ -1428,6 +1427,7 @@ unsigned int xhci_get_endpoint_index(struct usb_endpoint_descriptor *desc)
(usb_endpoint_dir_in(desc) ? 1 : 0) - 1;
return index;
}
+EXPORT_SYMBOL_GPL(xhci_get_endpoint_index);
/* The reverse operation to xhci_get_endpoint_index. Calculate the USB endpoint
* address from the XHCI endpoint index.
@@ -1860,8 +1860,8 @@ err_giveback:
* disabled, so there's no need for mutual exclusion to protect
* the xhci->devs[slot_id] structure.
*/
-static int xhci_drop_endpoint(struct usb_hcd *hcd, struct usb_device *udev,
- struct usb_host_endpoint *ep)
+int xhci_drop_endpoint(struct usb_hcd *hcd, struct usb_device *udev,
+ struct usb_host_endpoint *ep)
{
struct xhci_hcd *xhci;
struct xhci_container_ctx *in_ctx, *out_ctx;
@@ -1921,9 +1921,6 @@ static int xhci_drop_endpoint(struct usb_hcd *hcd, struct usb_device *udev,
xhci_endpoint_zero(xhci, xhci->devs[udev->slot_id], ep);
- if (xhci->quirks & XHCI_MTK_HOST)
- xhci_mtk_drop_ep_quirk(hcd, udev, ep);
-
xhci_dbg(xhci, "drop ep 0x%x, slot id %d, new drop flags = %#x, new add flags = %#x\n",
(unsigned int) ep->desc.bEndpointAddress,
udev->slot_id,
@@ -1931,6 +1928,7 @@ static int xhci_drop_endpoint(struct usb_hcd *hcd, struct usb_device *udev,
(unsigned int) new_add_flags);
return 0;
}
+EXPORT_SYMBOL_GPL(xhci_drop_endpoint);
/* Add an endpoint to a new possible bandwidth configuration for this device.
* Only one call to this function is allowed per endpoint before
@@ -1945,8 +1943,8 @@ static int xhci_drop_endpoint(struct usb_hcd *hcd, struct usb_device *udev,
* configuration or alt setting is installed in the device, so there's no need
* for mutual exclusion to protect the xhci->devs[slot_id] structure.
*/
-static int xhci_add_endpoint(struct usb_hcd *hcd, struct usb_device *udev,
- struct usb_host_endpoint *ep)
+int xhci_add_endpoint(struct usb_hcd *hcd, struct usb_device *udev,
+ struct usb_host_endpoint *ep)
{
struct xhci_hcd *xhci;
struct xhci_container_ctx *in_ctx;
@@ -2020,15 +2018,6 @@ static int xhci_add_endpoint(struct usb_hcd *hcd, struct usb_device *udev,
return -ENOMEM;
}
- if (xhci->quirks & XHCI_MTK_HOST) {
- ret = xhci_mtk_add_ep_quirk(hcd, udev, ep);
- if (ret < 0) {
- xhci_ring_free(xhci, virt_dev->eps[ep_index].new_ring);
- virt_dev->eps[ep_index].new_ring = NULL;
- return ret;
- }
- }
-
ctrl_ctx->add_flags |= cpu_to_le32(added_ctxs);
new_add_flags = le32_to_cpu(ctrl_ctx->add_flags);
@@ -2053,6 +2042,7 @@ static int xhci_add_endpoint(struct usb_hcd *hcd, struct usb_device *udev,
(unsigned int) new_add_flags);
return 0;
}
+EXPORT_SYMBOL_GPL(xhci_add_endpoint);
static void xhci_zero_in_ctx(struct xhci_hcd *xhci, struct xhci_virt_device *virt_dev)
{
@@ -3086,6 +3076,7 @@ command_cleanup:
return ret;
}
+EXPORT_SYMBOL_GPL(xhci_check_bandwidth);
void xhci_reset_bandwidth(struct usb_hcd *hcd, struct usb_device *udev)
{
@@ -3110,6 +3101,7 @@ void xhci_reset_bandwidth(struct usb_hcd *hcd, struct usb_device *udev)
}
xhci_zero_in_ctx(xhci, virt_dev);
}
+EXPORT_SYMBOL_GPL(xhci_reset_bandwidth);
static void xhci_setup_input_ctx_for_config_ep(struct xhci_hcd *xhci,
struct xhci_container_ctx *in_ctx,
@@ -5436,6 +5428,10 @@ void xhci_init_driver(struct hc_driver *drv,
drv->reset = over->reset;
if (over->start)
drv->start = over->start;
+ if (over->add_endpoint)
+ drv->add_endpoint = over->add_endpoint;
+ if (over->drop_endpoint)
+ drv->drop_endpoint = over->drop_endpoint;
if (over->check_bandwidth)
drv->check_bandwidth = over->check_bandwidth;
if (over->reset_bandwidth)
diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h
index ca822ad3b65b..2595a8f057c4 100644
--- a/drivers/usb/host/xhci.h
+++ b/drivers/usb/host/xhci.h
@@ -1929,6 +1929,10 @@ struct xhci_driver_overrides {
size_t extra_priv_size;
int (*reset)(struct usb_hcd *hcd);
int (*start)(struct usb_hcd *hcd);
+ int (*add_endpoint)(struct usb_hcd *hcd, struct usb_device *udev,
+ struct usb_host_endpoint *ep);
+ int (*drop_endpoint)(struct usb_hcd *hcd, struct usb_device *udev,
+ struct usb_host_endpoint *ep);
int (*check_bandwidth)(struct usb_hcd *, struct usb_device *);
void (*reset_bandwidth)(struct usb_hcd *, struct usb_device *);
};
@@ -2081,6 +2085,10 @@ int xhci_gen_setup(struct usb_hcd *hcd, xhci_get_quirks_t get_quirks);
void xhci_shutdown(struct usb_hcd *hcd);
void xhci_init_driver(struct hc_driver *drv,
const struct xhci_driver_overrides *over);
+int xhci_add_endpoint(struct usb_hcd *hcd, struct usb_device *udev,
+ struct usb_host_endpoint *ep);
+int xhci_drop_endpoint(struct usb_hcd *hcd, struct usb_device *udev,
+ struct usb_host_endpoint *ep);
int xhci_check_bandwidth(struct usb_hcd *hcd, struct usb_device *udev);
void xhci_reset_bandwidth(struct usb_hcd *hcd, struct usb_device *udev);
int xhci_disable_slot(struct xhci_hcd *xhci, u32 slot_id);
diff --git a/drivers/usb/typec/Kconfig b/drivers/usb/typec/Kconfig
index 270e81c087e9..a0418f23b4aa 100644
--- a/drivers/usb/typec/Kconfig
+++ b/drivers/usb/typec/Kconfig
@@ -50,6 +50,8 @@ source "drivers/usb/typec/tcpm/Kconfig"
source "drivers/usb/typec/ucsi/Kconfig"
+source "drivers/usb/typec/tipd/Kconfig"
+
config TYPEC_HD3SS3220
tristate "TI HD3SS3220 Type-C DRP Port controller driver"
depends on I2C
@@ -61,19 +63,6 @@ config TYPEC_HD3SS3220
If you choose to build this driver as a dynamically linked module, the
module will be called hd3ss3220.ko.
-config TYPEC_TPS6598X
- tristate "TI TPS6598x USB Power Delivery controller driver"
- depends on I2C
- select POWER_SUPPLY
- select REGMAP_I2C
- select USB_ROLE_SWITCH
- help
- Say Y or M here if your system has TI TPS65982 or TPS65983 USB Power
- Delivery controller.
-
- If you choose to build this driver as a dynamically linked module, the
- module will be called tps6598x.ko.
-
config TYPEC_STUSB160X
tristate "STMicroelectronics STUSB160x Type-C controller driver"
depends on I2C
diff --git a/drivers/usb/typec/Makefile b/drivers/usb/typec/Makefile
index d03b48c4b864..1fb8b6668b1b 100644
--- a/drivers/usb/typec/Makefile
+++ b/drivers/usb/typec/Makefile
@@ -4,8 +4,8 @@ typec-y := class.o mux.o bus.o
obj-$(CONFIG_TYPEC) += altmodes/
obj-$(CONFIG_TYPEC_TCPM) += tcpm/
obj-$(CONFIG_TYPEC_UCSI) += ucsi/
+obj-$(CONFIG_TYPEC_TPS6598X) += tipd/
obj-$(CONFIG_TYPEC_HD3SS3220) += hd3ss3220.o
-obj-$(CONFIG_TYPEC_TPS6598X) += tps6598x.o
obj-$(CONFIG_TYPEC_QCOM_PMIC) += qcom-pmic-typec.o
obj-$(CONFIG_TYPEC_STUSB160X) += stusb160x.o
obj-$(CONFIG_TYPEC) += mux/
diff --git a/drivers/usb/typec/stusb160x.c b/drivers/usb/typec/stusb160x.c
index d21750bbbb44..6eaeba9b096e 100644
--- a/drivers/usb/typec/stusb160x.c
+++ b/drivers/usb/typec/stusb160x.c
@@ -682,8 +682,8 @@ static int stusb160x_probe(struct i2c_client *client)
}
fwnode = device_get_named_child_node(chip->dev, "connector");
- if (IS_ERR(fwnode))
- return PTR_ERR(fwnode);
+ if (!fwnode)
+ return -ENODEV;
/*
* When both VDD and VSYS power supplies are present, the low power
diff --git a/drivers/usb/typec/tcpm/fusb302.c b/drivers/usb/typec/tcpm/fusb302.c
index ebc46b9f776c..7a2a17866a82 100644
--- a/drivers/usb/typec/tcpm/fusb302.c
+++ b/drivers/usb/typec/tcpm/fusb302.c
@@ -213,8 +213,9 @@ static void fusb302_debugfs_init(struct fusb302_chip *chip)
mutex_init(&chip->logbuffer_lock);
snprintf(name, NAME_MAX, "fusb302-%s", dev_name(chip->dev));
- chip->dentry = debugfs_create_file(name, S_IFREG | 0444, usb_debug_root,
- chip, &fusb302_debug_fops);
+ chip->dentry = debugfs_create_dir(name, usb_debug_root);
+ debugfs_create_file("log", S_IFREG | 0444, chip->dentry, chip,
+ &fusb302_debug_fops);
}
static void fusb302_debugfs_exit(struct fusb302_chip *chip)
diff --git a/drivers/usb/typec/tcpm/tcpci.c b/drivers/usb/typec/tcpm/tcpci.c
index a27deb0b5f03..25b480752266 100644
--- a/drivers/usb/typec/tcpm/tcpci.c
+++ b/drivers/usb/typec/tcpm/tcpci.c
@@ -24,6 +24,11 @@
#define AUTO_DISCHARGE_PD_HEADROOM_MV 850
#define AUTO_DISCHARGE_PPS_HEADROOM_MV 1250
+#define tcpc_presenting_rd(reg, cc) \
+ (!(TCPC_ROLE_CTRL_DRP & (reg)) && \
+ (((reg) & (TCPC_ROLE_CTRL_## cc ##_MASK << TCPC_ROLE_CTRL_## cc ##_SHIFT)) == \
+ (TCPC_ROLE_CTRL_CC_RD << TCPC_ROLE_CTRL_## cc ##_SHIFT)))
+
struct tcpci {
struct device *dev;
@@ -178,19 +183,25 @@ static int tcpci_get_cc(struct tcpc_dev *tcpc,
enum typec_cc_status *cc1, enum typec_cc_status *cc2)
{
struct tcpci *tcpci = tcpc_to_tcpci(tcpc);
- unsigned int reg;
+ unsigned int reg, role_control;
int ret;
+ ret = regmap_read(tcpci->regmap, TCPC_ROLE_CTRL, &role_control);
+ if (ret < 0)
+ return ret;
+
ret = regmap_read(tcpci->regmap, TCPC_CC_STATUS, &reg);
if (ret < 0)
return ret;
*cc1 = tcpci_to_typec_cc((reg >> TCPC_CC_STATUS_CC1_SHIFT) &
TCPC_CC_STATUS_CC1_MASK,
- reg & TCPC_CC_STATUS_TERM);
+ reg & TCPC_CC_STATUS_TERM ||
+ tcpc_presenting_rd(role_control, CC1));
*cc2 = tcpci_to_typec_cc((reg >> TCPC_CC_STATUS_CC2_SHIFT) &
TCPC_CC_STATUS_CC2_MASK,
- reg & TCPC_CC_STATUS_TERM);
+ reg & TCPC_CC_STATUS_TERM ||
+ tcpc_presenting_rd(role_control, CC2));
return 0;
}
diff --git a/drivers/usb/typec/tcpm/tcpm.c b/drivers/usb/typec/tcpm/tcpm.c
index be0b6469dd3d..11d0c40bc47d 100644
--- a/drivers/usb/typec/tcpm/tcpm.c
+++ b/drivers/usb/typec/tcpm/tcpm.c
@@ -438,6 +438,9 @@ struct tcpm_port {
enum tcpm_ams next_ams;
bool in_ams;
+ /* Auto vbus discharge status */
+ bool auto_vbus_discharge_enabled;
+
#ifdef CONFIG_DEBUG_FS
struct dentry *dentry;
struct mutex logbuffer_lock; /* log buffer access lock */
@@ -507,6 +510,9 @@ static const char * const pd_rev[] = {
(tcpm_port_is_sink(port) && \
((port)->cc1 == TYPEC_CC_RP_3_0 || (port)->cc2 == TYPEC_CC_RP_3_0))
+#define tcpm_wait_for_discharge(port) \
+ (((port)->auto_vbus_discharge_enabled && !(port)->vbus_vsafe0v) ? PD_T_SAFE_0V : 0)
+
static enum tcpm_state tcpm_default_state(struct tcpm_port *port)
{
if (port->port_type == TYPEC_PORT_DRP) {
@@ -703,8 +709,9 @@ static void tcpm_debugfs_init(struct tcpm_port *port)
mutex_init(&port->logbuffer_lock);
snprintf(name, NAME_MAX, "tcpm-%s", dev_name(port->dev));
- port->dentry = debugfs_create_file(name, S_IFREG | 0444, usb_debug_root,
- port, &tcpm_debug_fops);
+ port->dentry = debugfs_create_dir(name, usb_debug_root);
+ debugfs_create_file("log", S_IFREG | 0444, port->dentry, port,
+ &tcpm_debug_fops);
}
static void tcpm_debugfs_exit(struct tcpm_port *port)
@@ -773,10 +780,8 @@ static enum typec_cc_status tcpm_rp_cc(struct tcpm_port *port)
return TYPEC_CC_RP_DEF;
}
-static int tcpm_ams_finish(struct tcpm_port *port)
+static void tcpm_ams_finish(struct tcpm_port *port)
{
- int ret = 0;
-
tcpm_log(port, "AMS %s finished", tcpm_ams_str[port->ams]);
if (port->pd_capable && port->pwr_role == TYPEC_SOURCE) {
@@ -790,8 +795,6 @@ static int tcpm_ams_finish(struct tcpm_port *port)
port->in_ams = false;
port->ams = NONE_AMS;
-
- return ret;
}
static int tcpm_pd_transmit(struct tcpm_port *port,
@@ -3413,6 +3416,8 @@ static int tcpm_src_attach(struct tcpm_port *port)
if (port->tcpc->enable_auto_vbus_discharge) {
ret = port->tcpc->enable_auto_vbus_discharge(port->tcpc, true);
tcpm_log_force(port, "enable vbus discharge ret:%d", ret);
+ if (!ret)
+ port->auto_vbus_discharge_enabled = true;
}
ret = tcpm_set_roles(port, true, TYPEC_SOURCE, tcpm_data_role_for_source(port));
@@ -3495,6 +3500,8 @@ static void tcpm_reset_port(struct tcpm_port *port)
if (port->tcpc->enable_auto_vbus_discharge) {
ret = port->tcpc->enable_auto_vbus_discharge(port->tcpc, false);
tcpm_log_force(port, "Disable vbus discharge ret:%d", ret);
+ if (!ret)
+ port->auto_vbus_discharge_enabled = false;
}
port->in_ams = false;
port->ams = NONE_AMS;
@@ -3568,6 +3575,8 @@ static int tcpm_snk_attach(struct tcpm_port *port)
tcpm_set_auto_vbus_discharge_threshold(port, TYPEC_PWR_MODE_USB, false, VSAFE5V);
ret = port->tcpc->enable_auto_vbus_discharge(port->tcpc, true);
tcpm_log_force(port, "enable vbus discharge ret:%d", ret);
+ if (!ret)
+ port->auto_vbus_discharge_enabled = true;
}
ret = tcpm_set_roles(port, true, TYPEC_SINK, tcpm_data_role_for_sink(port));
@@ -4670,9 +4679,9 @@ static void _tcpm_cc_change(struct tcpm_port *port, enum typec_cc_status cc1,
if (tcpm_port_is_disconnected(port) ||
!tcpm_port_is_source(port)) {
if (port->port_type == TYPEC_PORT_SRC)
- tcpm_set_state(port, SRC_UNATTACHED, 0);
+ tcpm_set_state(port, SRC_UNATTACHED, tcpm_wait_for_discharge(port));
else
- tcpm_set_state(port, SNK_UNATTACHED, 0);
+ tcpm_set_state(port, SNK_UNATTACHED, tcpm_wait_for_discharge(port));
}
break;
case SNK_UNATTACHED:
@@ -4703,7 +4712,23 @@ static void _tcpm_cc_change(struct tcpm_port *port, enum typec_cc_status cc1,
tcpm_set_state(port, SNK_DEBOUNCED, 0);
break;
case SNK_READY:
- if (tcpm_port_is_disconnected(port))
+ /*
+ * EXIT condition is based primarily on vbus disconnect and CC is secondary.
+ * "A port that has entered into USB PD communications with the Source and
+ * has seen the CC voltage exceed vRd-USB may monitor the CC pin to detect
+ * cable disconnect in addition to monitoring VBUS.
+ *
+ * A port that is monitoring the CC voltage for disconnect (but is not in
+ * the process of a USB PD PR_Swap or USB PD FR_Swap) shall transition to
+ * Unattached.SNK within tSinkDisconnect after the CC voltage remains below
+ * vRd-USB for tPDDebounce."
+ *
+ * When set_auto_vbus_discharge_threshold is enabled, CC pins go
+ * away before vbus decays to disconnect threshold. Allow
+ * disconnect to be driven by vbus disconnect when auto vbus
+ * discharge is enabled.
+ */
+ if (!port->auto_vbus_discharge_enabled && tcpm_port_is_disconnected(port))
tcpm_set_state(port, unattached_state(port), 0);
else if (!port->pd_capable &&
(cc1 != old_cc1 || cc2 != old_cc2))
@@ -4802,9 +4827,13 @@ static void _tcpm_cc_change(struct tcpm_port *port, enum typec_cc_status cc1,
* Ignore CC changes here.
*/
break;
-
default:
- if (tcpm_port_is_disconnected(port))
+ /*
+ * While acting as sink and auto vbus discharge is enabled, Allow disconnect
+ * to be driven by vbus disconnect.
+ */
+ if (tcpm_port_is_disconnected(port) && !(port->pwr_role == TYPEC_SINK &&
+ port->auto_vbus_discharge_enabled))
tcpm_set_state(port, unattached_state(port), 0);
break;
}
@@ -4968,8 +4997,16 @@ static void _tcpm_pd_vbus_off(struct tcpm_port *port)
case SRC_TRANSITION_SUPPLY:
case SRC_READY:
case SRC_WAIT_NEW_CAPABILITIES:
- /* Force to unattached state to re-initiate connection */
- tcpm_set_state(port, SRC_UNATTACHED, 0);
+ /*
+ * Force to unattached state to re-initiate connection.
+ * DRP port should move to Unattached.SNK instead of Unattached.SRC if
+ * sink removed. Although sink removal here is due to source's vbus collapse,
+ * treat it the same way for consistency.
+ */
+ if (port->port_type == TYPEC_PORT_SRC)
+ tcpm_set_state(port, SRC_UNATTACHED, tcpm_wait_for_discharge(port));
+ else
+ tcpm_set_state(port, SNK_UNATTACHED, tcpm_wait_for_discharge(port));
break;
case PORT_RESET:
@@ -4988,9 +5025,8 @@ static void _tcpm_pd_vbus_off(struct tcpm_port *port)
break;
default:
- if (port->pwr_role == TYPEC_SINK &&
- port->attached)
- tcpm_set_state(port, SNK_UNATTACHED, 0);
+ if (port->pwr_role == TYPEC_SINK && port->attached)
+ tcpm_set_state(port, SNK_UNATTACHED, tcpm_wait_for_discharge(port));
break;
}
}
@@ -5012,7 +5048,23 @@ static void _tcpm_pd_vbus_vsafe0v(struct tcpm_port *port)
tcpm_set_state(port, tcpm_try_snk(port) ? SNK_TRY : SRC_ATTACHED,
PD_T_CC_DEBOUNCE);
break;
+ case SRC_STARTUP:
+ case SRC_SEND_CAPABILITIES:
+ case SRC_SEND_CAPABILITIES_TIMEOUT:
+ case SRC_NEGOTIATE_CAPABILITIES:
+ case SRC_TRANSITION_SUPPLY:
+ case SRC_READY:
+ case SRC_WAIT_NEW_CAPABILITIES:
+ if (port->auto_vbus_discharge_enabled) {
+ if (port->port_type == TYPEC_PORT_SRC)
+ tcpm_set_state(port, SRC_UNATTACHED, 0);
+ else
+ tcpm_set_state(port, SNK_UNATTACHED, 0);
+ }
+ break;
default:
+ if (port->pwr_role == TYPEC_SINK && port->auto_vbus_discharge_enabled)
+ tcpm_set_state(port, SNK_UNATTACHED, 0);
break;
}
}
diff --git a/drivers/usb/typec/tipd/Kconfig b/drivers/usb/typec/tipd/Kconfig
new file mode 100644
index 000000000000..b82715293072
--- /dev/null
+++ b/drivers/usb/typec/tipd/Kconfig
@@ -0,0 +1,12 @@
+config TYPEC_TPS6598X
+ tristate "TI TPS6598x USB Power Delivery controller driver"
+ depends on I2C
+ select POWER_SUPPLY
+ select REGMAP_I2C
+ select USB_ROLE_SWITCH
+ help
+ Say Y or M here if your system has TI TPS65982 or TPS65983 USB Power
+ Delivery controller.
+
+ If you choose to build this driver as a dynamically linked module, the
+ module will be called tps6598x.ko.
diff --git a/drivers/usb/typec/tipd/Makefile b/drivers/usb/typec/tipd/Makefile
new file mode 100644
index 000000000000..aa439f80a889
--- /dev/null
+++ b/drivers/usb/typec/tipd/Makefile
@@ -0,0 +1,6 @@
+# SPDX-License-Identifier: GPL-2.0
+CFLAGS_trace.o := -I$(src)
+
+obj-$(CONFIG_TYPEC_TPS6598X) += tps6598x.o
+tps6598x-y := core.o
+tps6598x-$(CONFIG_TRACING) += trace.o
diff --git a/drivers/usb/typec/tps6598x.c b/drivers/usb/typec/tipd/core.c
index 6e6ef6317523..9e924db42179 100644
--- a/drivers/usb/typec/tps6598x.c
+++ b/drivers/usb/typec/tipd/core.c
@@ -15,6 +15,9 @@
#include <linux/usb/typec.h>
#include <linux/usb/role.h>
+#include "tps6598x.h"
+#include "trace.h"
+
/* Register offsets */
#define TPS_REG_VID 0x00
#define TPS_REG_MODE 0x03
@@ -31,16 +34,7 @@
#define TPS_REG_CTRL_CONF 0x29
#define TPS_REG_POWER_STATUS 0x3f
#define TPS_REG_RX_IDENTITY_SOP 0x48
-
-/* TPS_REG_INT_* bits */
-#define TPS_REG_INT_PLUG_EVENT BIT(3)
-
-/* TPS_REG_STATUS bits */
-#define TPS_STATUS_PLUG_PRESENT BIT(0)
-#define TPS_STATUS_ORIENTATION BIT(4)
-#define TPS_STATUS_PORTROLE(s) (!!((s) & BIT(5)))
-#define TPS_STATUS_DATAROLE(s) (!!((s) & BIT(6)))
-#define TPS_STATUS_VCONN(s) (!!((s) & BIT(7)))
+#define TPS_REG_DATA_STATUS 0x5f
/* TPS_REG_SYSTEM_CONF bits */
#define TPS_SYSCONF_PORTINFO(c) ((c) & 7)
@@ -55,11 +49,6 @@ enum {
TPS_PORTINFO_SOURCE,
};
-/* TPS_REG_POWER_STATUS bits */
-#define TPS_POWER_STATUS_CONNECTION BIT(0)
-#define TPS_POWER_STATUS_SOURCESINK BIT(1)
-#define TPS_POWER_STATUS_PWROPMODE(p) (((p) & GENMASK(3, 2)) >> 2)
-
/* TPS_REG_RX_IDENTITY_SOP */
struct tps6598x_rx_identity_reg {
u8 status;
@@ -256,9 +245,9 @@ static int tps6598x_connect(struct tps6598x *tps, u32 status)
}
typec_set_pwr_opmode(tps->port, mode);
- typec_set_pwr_role(tps->port, TPS_STATUS_PORTROLE(status));
- typec_set_vconn_role(tps->port, TPS_STATUS_VCONN(status));
- tps6598x_set_data_role(tps, TPS_STATUS_DATAROLE(status), true);
+ typec_set_pwr_role(tps->port, TPS_STATUS_TO_TYPEC_PORTROLE(status));
+ typec_set_vconn_role(tps->port, TPS_STATUS_TO_TYPEC_VCONN(status));
+ tps6598x_set_data_role(tps, TPS_STATUS_TO_TYPEC_DATAROLE(status), true);
tps->partner = typec_register_partner(tps->port, &desc);
if (IS_ERR(tps->partner))
@@ -278,9 +267,10 @@ static void tps6598x_disconnect(struct tps6598x *tps, u32 status)
typec_unregister_partner(tps->partner);
tps->partner = NULL;
typec_set_pwr_opmode(tps->port, TYPEC_PWR_MODE_USB);
- typec_set_pwr_role(tps->port, TPS_STATUS_PORTROLE(status));
- typec_set_vconn_role(tps->port, TPS_STATUS_VCONN(status));
- tps6598x_set_data_role(tps, TPS_STATUS_DATAROLE(status), false);
+ typec_set_pwr_role(tps->port, TPS_STATUS_TO_TYPEC_PORTROLE(status));
+ typec_set_vconn_role(tps->port, TPS_STATUS_TO_TYPEC_VCONN(status));
+ tps6598x_set_data_role(tps, TPS_STATUS_TO_TYPEC_DATAROLE(status), false);
+
power_supply_changed(tps->psy);
}
@@ -364,7 +354,7 @@ static int tps6598x_dr_set(struct typec_port *port, enum typec_data_role role)
if (ret)
goto out_unlock;
- if (role != TPS_STATUS_DATAROLE(status)) {
+ if (role != TPS_STATUS_TO_TYPEC_DATAROLE(status)) {
ret = -EPROTO;
goto out_unlock;
}
@@ -394,7 +384,7 @@ static int tps6598x_pr_set(struct typec_port *port, enum typec_role role)
if (ret)
goto out_unlock;
- if (role != TPS_STATUS_PORTROLE(status)) {
+ if (role != TPS_STATUS_TO_TYPEC_PORTROLE(status)) {
ret = -EPROTO;
goto out_unlock;
}
@@ -417,7 +407,8 @@ static irqreturn_t tps6598x_interrupt(int irq, void *data)
struct tps6598x *tps = data;
u64 event1;
u64 event2;
- u32 status;
+ u32 status, data_status;
+ u16 pwr_status;
int ret;
mutex_lock(&tps->lock);
@@ -428,12 +419,32 @@ static irqreturn_t tps6598x_interrupt(int irq, void *data)
dev_err(tps->dev, "%s: failed to read events\n", __func__);
goto err_unlock;
}
+ trace_tps6598x_irq(event1, event2);
ret = tps6598x_read32(tps, TPS_REG_STATUS, &status);
if (ret) {
dev_err(tps->dev, "%s: failed to read status\n", __func__);
goto err_clear_ints;
}
+ trace_tps6598x_status(status);
+
+ if ((event1 | event2) & TPS_REG_INT_POWER_STATUS_UPDATE) {
+ ret = tps6598x_read16(tps, TPS_REG_POWER_STATUS, &pwr_status);
+ if (ret < 0) {
+ dev_err(tps->dev, "failed to read power status: %d\n", ret);
+ goto err_clear_ints;
+ }
+ trace_tps6598x_power_status(pwr_status);
+ }
+
+ if ((event1 | event2) & TPS_REG_INT_DATA_STATUS_UPDATE) {
+ ret = tps6598x_read32(tps, TPS_REG_DATA_STATUS, &data_status);
+ if (ret < 0) {
+ dev_err(tps->dev, "failed to read data status: %d\n", ret);
+ goto err_clear_ints;
+ }
+ trace_tps6598x_data_status(data_status);
+ }
/* Handle plug insert or removal */
if ((event1 | event2) & TPS_REG_INT_PLUG_EVENT) {
@@ -499,8 +510,8 @@ static int tps6598x_psy_get_online(struct tps6598x *tps,
if (ret < 0)
return ret;
- if ((pwr_status & TPS_POWER_STATUS_CONNECTION) &&
- (pwr_status & TPS_POWER_STATUS_SOURCESINK)) {
+ if (TPS_POWER_STATUS_CONNECTION(pwr_status) &&
+ TPS_POWER_STATUS_SOURCESINK(pwr_status)) {
val->intval = 1;
} else {
val->intval = 0;
@@ -609,14 +620,15 @@ static int tps6598x_probe(struct i2c_client *client)
ret = tps6598x_read32(tps, TPS_REG_STATUS, &status);
if (ret < 0)
return ret;
+ trace_tps6598x_status(status);
ret = tps6598x_read32(tps, TPS_REG_SYSTEM_CONF, &conf);
if (ret < 0)
return ret;
fwnode = device_get_named_child_node(&client->dev, "connector");
- if (IS_ERR(fwnode))
- return PTR_ERR(fwnode);
+ if (!fwnode)
+ return -ENODEV;
tps->role_sw = fwnode_usb_role_switch_get(fwnode);
if (IS_ERR(tps->role_sw)) {
diff --git a/drivers/usb/typec/tipd/tps6598x.h b/drivers/usb/typec/tipd/tps6598x.h
new file mode 100644
index 000000000000..003a577be216
--- /dev/null
+++ b/drivers/usb/typec/tipd/tps6598x.h
@@ -0,0 +1,189 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Driver for TI TPS6598x USB Power Delivery controller family
+ *
+ * Copyright (C) 2017, Intel Corporation
+ * Author: Heikki Krogerus <heikki.krogerus@linux.intel.com>
+ */
+
+#include <linux/bits.h>
+#include <linux/bitfield.h>
+
+#ifndef __TPS6598X_H__
+#define __TPS6598X_H__
+
+#define TPS_FIELD_GET(_mask, _reg) ((typeof(_mask))(((_reg) & (_mask)) >> __bf_shf(_mask)))
+
+/* TPS_REG_STATUS bits */
+#define TPS_STATUS_PLUG_PRESENT BIT(0)
+#define TPS_STATUS_PLUG_UPSIDE_DOWN BIT(4)
+#define TPS_STATUS_PORTROLE BIT(5)
+#define TPS_STATUS_TO_TYPEC_PORTROLE(s) (!!((s) & TPS_STATUS_PORTROLE))
+#define TPS_STATUS_DATAROLE BIT(6)
+#define TPS_STATUS_TO_TYPEC_DATAROLE(s) (!!((s) & TPS_STATUS_DATAROLE))
+#define TPS_STATUS_VCONN BIT(7)
+#define TPS_STATUS_TO_TYPEC_VCONN(s) (!!((s) & TPS_STATUS_VCONN))
+#define TPS_STATUS_OVERCURRENT BIT(16)
+#define TPS_STATUS_GOTO_MIN_ACTIVE BIT(26)
+#define TPS_STATUS_BIST BIT(27)
+#define TPS_STATUS_HIGH_VOLAGE_WARNING BIT(28)
+#define TPS_STATUS_HIGH_LOW_VOLTAGE_WARNING BIT(29)
+
+#define TPS_STATUS_CONN_STATE_MASK GENMASK(3, 1)
+#define TPS_STATUS_CONN_STATE(x) TPS_FIELD_GET(TPS_STATUS_CONN_STATE_MASK, (x))
+#define TPS_STATUS_PP_5V0_SWITCH_MASK GENMASK(9, 8)
+#define TPS_STATUS_PP_5V0_SWITCH(x) TPS_FIELD_GET(TPS_STATUS_PP_5V0_SWITCH_MASK, (x))
+#define TPS_STATUS_PP_HV_SWITCH_MASK GENMASK(11, 10)
+#define TPS_STATUS_PP_HV_SWITCH(x) TPS_FIELD_GET(TPS_STATUS_PP_HV_SWITCH_MASK, (x))
+#define TPS_STATUS_PP_EXT_SWITCH_MASK GENMASK(13, 12)
+#define TPS_STATUS_PP_EXT_SWITCH(x) TPS_FIELD_GET(TPS_STATUS_PP_EXT_SWITCH_MASK, (x))
+#define TPS_STATUS_PP_CABLE_SWITCH_MASK GENMASK(15, 14)
+#define TPS_STATUS_PP_CABLE_SWITCH(x) TPS_FIELD_GET(TPS_STATUS_PP_CABLE_SWITCH_MASK, (x))
+#define TPS_STATUS_POWER_SOURCE_MASK GENMASK(19, 18)
+#define TPS_STATUS_POWER_SOURCE(x) TPS_FIELD_GET(TPS_STATUS_POWER_SOURCE_MASK, (x))
+#define TPS_STATUS_VBUS_STATUS_MASK GENMASK(21, 20)
+#define TPS_STATUS_VBUS_STATUS(x) TPS_FIELD_GET(TPS_STATUS_VBUS_STATUS_MASK, (x))
+#define TPS_STATUS_USB_HOST_PRESENT_MASK GENMASK(23, 22)
+#define TPS_STATUS_USB_HOST_PRESENT(x) TPS_FIELD_GET(TPS_STATUS_USB_HOST_PRESENT_MASK, (x))
+#define TPS_STATUS_LEGACY_MASK GENMASK(25, 24)
+#define TPS_STATUS_LEGACY(x) TPS_FIELD_GET(TPS_STATUS_LEGACY_MASK, (x))
+
+#define TPS_STATUS_CONN_STATE_NO_CONN 0
+#define TPS_STATUS_CONN_STATE_DISABLED 1
+#define TPS_STATUS_CONN_STATE_AUDIO_CONN 2
+#define TPS_STATUS_CONN_STATE_DEBUG_CONN 3
+#define TPS_STATUS_CONN_STATE_NO_CONN_R_A 4
+#define TPS_STATUS_CONN_STATE_RESERVED 5
+#define TPS_STATUS_CONN_STATE_CONN_NO_R_A 6
+#define TPS_STATUS_CONN_STATE_CONN_WITH_R_A 7
+
+#define TPS_STATUS_PP_SWITCH_STATE_DISABLED 0
+#define TPS_STATUS_PP_SWITCH_STATE_FAULT 1
+#define TPS_STATUS_PP_SWITCH_STATE_OUT 2
+#define TPS_STATUS_PP_SWITCH_STATE_IN 3
+
+#define TPS_STATUS_POWER_SOURCE_UNKNOWN 0
+#define TPS_STATUS_POWER_SOURCE_VIN_3P3 1
+#define TPS_STATUS_POWER_SOURCE_DEAD_BAT 2
+#define TPS_STATUS_POWER_SOURCE_VBUS 3
+
+#define TPS_STATUS_VBUS_STATUS_VSAFE0V 0
+#define TPS_STATUS_VBUS_STATUS_VSAFE5V 1
+#define TPS_STATUS_VBUS_STATUS_PD 2
+#define TPS_STATUS_VBUS_STATUS_FAULT 3
+
+#define TPS_STATUS_USB_HOST_PRESENT_NO 0
+#define TPS_STATUS_USB_HOST_PRESENT_PD_NO_USB 1
+#define TPS_STATUS_USB_HOST_PRESENT_NO_PD 2
+#define TPS_STATUS_USB_HOST_PRESENT_PD_USB 3
+
+#define TPS_STATUS_LEGACY_NO 0
+#define TPS_STATUS_LEGACY_SINK 1
+#define TPS_STATUS_LEGACY_SOURCE 2
+
+/* TPS_REG_INT_* bits */
+#define TPS_REG_INT_USER_VID_ALT_MODE_OTHER_VDM BIT_ULL(27+32)
+#define TPS_REG_INT_USER_VID_ALT_MODE_ATTN_VDM BIT_ULL(26+32)
+#define TPS_REG_INT_USER_VID_ALT_MODE_EXIT BIT_ULL(25+32)
+#define TPS_REG_INT_USER_VID_ALT_MODE_ENTERED BIT_ULL(24+32)
+#define TPS_REG_INT_EXIT_MODES_COMPLETE BIT_ULL(20+32)
+#define TPS_REG_INT_DISCOVER_MODES_COMPLETE BIT_ULL(19+32)
+#define TPS_REG_INT_VDM_MSG_SENT BIT_ULL(18+32)
+#define TPS_REG_INT_VDM_ENTERED_MODE BIT_ULL(17+32)
+#define TPS_REG_INT_ERROR_UNABLE_TO_SOURCE BIT_ULL(14+32)
+#define TPS_REG_INT_SRC_TRANSITION BIT_ULL(10+32)
+#define TPS_REG_INT_ERROR_DISCHARGE_FAILED BIT_ULL(9+32)
+#define TPS_REG_INT_ERROR_MESSAGE_DATA BIT_ULL(7+32)
+#define TPS_REG_INT_ERROR_PROTOCOL_ERROR BIT_ULL(6+32)
+#define TPS_REG_INT_ERROR_MISSING_GET_CAP_MESSAGE BIT_ULL(4+32)
+#define TPS_REG_INT_ERROR_POWER_EVENT_OCCURRED BIT_ULL(3+32)
+#define TPS_REG_INT_ERROR_CAN_PROVIDE_PWR_LATER BIT_ULL(2+32)
+#define TPS_REG_INT_ERROR_CANNOT_PROVIDE_PWR BIT_ULL(1+32)
+#define TPS_REG_INT_ERROR_DEVICE_INCOMPATIBLE BIT_ULL(0+32)
+#define TPS_REG_INT_CMD2_COMPLETE BIT(31)
+#define TPS_REG_INT_CMD1_COMPLETE BIT(30)
+#define TPS_REG_INT_ADC_HIGH_THRESHOLD BIT(29)
+#define TPS_REG_INT_ADC_LOW_THRESHOLD BIT(28)
+#define TPS_REG_INT_PD_STATUS_UPDATE BIT(27)
+#define TPS_REG_INT_STATUS_UPDATE BIT(26)
+#define TPS_REG_INT_DATA_STATUS_UPDATE BIT(25)
+#define TPS_REG_INT_POWER_STATUS_UPDATE BIT(24)
+#define TPS_REG_INT_PP_SWITCH_CHANGED BIT(23)
+#define TPS_REG_INT_HIGH_VOLTAGE_WARNING BIT(22)
+#define TPS_REG_INT_USB_HOST_PRESENT_NO_LONGER BIT(21)
+#define TPS_REG_INT_USB_HOST_PRESENT BIT(20)
+#define TPS_REG_INT_GOTO_MIN_RECEIVED BIT(19)
+#define TPS_REG_INT_PR_SWAP_REQUESTED BIT(17)
+#define TPS_REG_INT_SINK_CAP_MESSAGE_READY BIT(15)
+#define TPS_REG_INT_SOURCE_CAP_MESSAGE_READY BIT(14)
+#define TPS_REG_INT_NEW_CONTRACT_AS_PROVIDER BIT(13)
+#define TPS_REG_INT_NEW_CONTRACT_AS_CONSUMER BIT(12)
+#define TPS_REG_INT_VDM_RECEIVED BIT(11)
+#define TPS_REG_INT_ATTENTION_RECEIVED BIT(10)
+#define TPS_REG_INT_OVERCURRENT BIT(9)
+#define TPS_REG_INT_BIST BIT(8)
+#define TPS_REG_INT_RDO_RECEIVED_FROM_SINK BIT(7)
+#define TPS_REG_INT_DR_SWAP_COMPLETE BIT(5)
+#define TPS_REG_INT_PR_SWAP_COMPLETE BIT(4)
+#define TPS_REG_INT_PLUG_EVENT BIT(3)
+#define TPS_REG_INT_HARD_RESET BIT(1)
+#define TPS_REG_INT_PD_SOFT_RESET BIT(0)
+
+/* TPS_REG_POWER_STATUS bits */
+#define TPS_POWER_STATUS_CONNECTION(x) TPS_FIELD_GET(BIT(0), (x))
+#define TPS_POWER_STATUS_SOURCESINK(x) TPS_FIELD_GET(BIT(1), (x))
+#define TPS_POWER_STATUS_BC12_DET(x) TPS_FIELD_GET(BIT(2), (x))
+
+#define TPS_POWER_STATUS_TYPEC_CURRENT_MASK GENMASK(3, 2)
+#define TPS_POWER_STATUS_PWROPMODE(p) TPS_FIELD_GET(TPS_POWER_STATUS_TYPEC_CURRENT_MASK, (p))
+#define TPS_POWER_STATUS_BC12_STATUS_MASK GENMASK(6, 5)
+#define TPS_POWER_STATUS_BC12_STATUS(p) TPS_FIELD_GET(TPS_POWER_STATUS_BC12_STATUS_MASK, (p))
+
+#define TPS_POWER_STATUS_TYPEC_CURRENT_USB 0
+#define TPS_POWER_STATUS_TYPEC_CURRENT_1A5 1
+#define TPS_POWER_STATUS_TYPEC_CURRENT_3A0 2
+#define TPS_POWER_STATUS_TYPEC_CURRENT_PD 3
+
+#define TPS_POWER_STATUS_BC12_STATUS_SDP 0
+#define TPS_POWER_STATUS_BC12_STATUS_CDP 2
+#define TPS_POWER_STATUS_BC12_STATUS_DCP 3
+
+/* TPS_REG_DATA_STATUS bits */
+#define TPS_DATA_STATUS_DATA_CONNECTION BIT(0)
+#define TPS_DATA_STATUS_UPSIDE_DOWN BIT(1)
+#define TPS_DATA_STATUS_ACTIVE_CABLE BIT(2)
+#define TPS_DATA_STATUS_USB2_CONNECTION BIT(4)
+#define TPS_DATA_STATUS_USB3_CONNECTION BIT(5)
+#define TPS_DATA_STATUS_USB3_GEN2 BIT(6)
+#define TPS_DATA_STATUS_USB_DATA_ROLE BIT(7)
+#define TPS_DATA_STATUS_DP_CONNECTION BIT(8)
+#define TPS_DATA_STATUS_DP_SINK BIT(9)
+#define TPS_DATA_STATUS_TBT_CONNECTION BIT(16)
+#define TPS_DATA_STATUS_TBT_TYPE BIT(17)
+#define TPS_DATA_STATUS_OPTICAL_CABLE BIT(18)
+#define TPS_DATA_STATUS_ACTIVE_LINK_TRAIN BIT(20)
+#define TPS_DATA_STATUS_FORCE_LSX BIT(23)
+#define TPS_DATA_STATUS_POWER_MISMATCH BIT(24)
+
+#define TPS_DATA_STATUS_DP_PIN_ASSIGNMENT_MASK GENMASK(11, 10)
+#define TPS_DATA_STATUS_DP_PIN_ASSIGNMENT(x) \
+ TPS_FIELD_GET(TPS_DATA_STATUS_DP_PIN_ASSIGNMENT_MASK, (x))
+#define TPS_DATA_STATUS_TBT_CABLE_SPEED_MASK GENMASK(27, 25)
+#define TPS_DATA_STATUS_TBT_CABLE_SPEED \
+ TPS_FIELD_GET(TPS_DATA_STATUS_TBT_CABLE_SPEED_MASK, (x))
+#define TPS_DATA_STATUS_TBT_CABLE_GEN_MASK GENMASK(29, 28)
+#define TPS_DATA_STATUS_TBT_CABLE_GEN \
+ TPS_FIELD_GET(TPS_DATA_STATUS_TBT_CABLE_GEN_MASK, (x))
+
+/* Map data status to DP spec assignments */
+#define TPS_DATA_STATUS_DP_SPEC_PIN_ASSIGNMENT(x) \
+ ((TPS_DATA_STATUS_DP_PIN_ASSIGNMENT(x) << 1) | \
+ TPS_FIELD_GET(TPS_DATA_STATUS_USB3_CONNECTION, (x)))
+#define TPS_DATA_STATUS_DP_SPEC_PIN_ASSIGNMENT_E 0
+#define TPS_DATA_STATUS_DP_SPEC_PIN_ASSIGNMENT_F BIT(0)
+#define TPS_DATA_STATUS_DP_SPEC_PIN_ASSIGNMENT_C BIT(1)
+#define TPS_DATA_STATUS_DP_SPEC_PIN_ASSIGNMENT_D (BIT(1) | BIT(0))
+#define TPS_DATA_STATUS_DP_SPEC_PIN_ASSIGNMENT_A BIT(2)
+#define TPS_DATA_STATUS_DP_SPEC_PIN_ASSIGNMENT_B (BIT(2) | BIT(1))
+
+#endif /* __TPS6598X_H__ */
diff --git a/drivers/usb/typec/tipd/trace.c b/drivers/usb/typec/tipd/trace.c
new file mode 100644
index 000000000000..016e68048dc2
--- /dev/null
+++ b/drivers/usb/typec/tipd/trace.c
@@ -0,0 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * TI TPS6598x USB Power Delivery Controller Trace Support
+ *
+ * Copyright (C) 2021, Intel Corporation
+ * Author: Heikki Krogerus <heikki.krogerus@linux.intel.com>
+ */
+#define CREATE_TRACE_POINTS
+#include "trace.h"
diff --git a/drivers/usb/typec/tipd/trace.h b/drivers/usb/typec/tipd/trace.h
new file mode 100644
index 000000000000..5d09d6f78930
--- /dev/null
+++ b/drivers/usb/typec/tipd/trace.h
@@ -0,0 +1,283 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Driver for TI TPS6598x USB Power Delivery controller family
+ *
+ * Copyright (C) 2020 Purism SPC
+ * Author: Guido Günther <agx@sigxcpu.org>
+ */
+
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM tps6598x
+
+#if !defined(_TPS6598X_TRACE_H_) || defined(TRACE_HEADER_MULTI_READ)
+#define _TPS6598X_TRACE_H_
+
+#include "tps6598x.h"
+
+#include <linux/stringify.h>
+#include <linux/types.h>
+#include <linux/tracepoint.h>
+
+#define show_irq_flags(flags) \
+ __print_flags_u64(flags, "|", \
+ { TPS_REG_INT_PD_SOFT_RESET, "PD_SOFT_RESET" }, \
+ { TPS_REG_INT_HARD_RESET, "HARD_RESET" }, \
+ { TPS_REG_INT_PLUG_EVENT, "PLUG_EVENT" }, \
+ { TPS_REG_INT_PR_SWAP_COMPLETE, "PR_SWAP_COMPLETE" }, \
+ { TPS_REG_INT_DR_SWAP_COMPLETE, "DR_SWAP_COMPLETE" }, \
+ { TPS_REG_INT_RDO_RECEIVED_FROM_SINK, "RDO_RECEIVED_FROM_SINK" }, \
+ { TPS_REG_INT_BIST, "BIST" }, \
+ { TPS_REG_INT_OVERCURRENT, "OVERCURRENT" }, \
+ { TPS_REG_INT_ATTENTION_RECEIVED, "ATTENTION_RECEIVED" }, \
+ { TPS_REG_INT_VDM_RECEIVED, "VDM_RECEIVED" }, \
+ { TPS_REG_INT_NEW_CONTRACT_AS_CONSUMER, "NEW_CONTRACT_AS_CONSUMER" }, \
+ { TPS_REG_INT_NEW_CONTRACT_AS_PROVIDER, "NEW_CONTRACT_AS_PROVIDER" }, \
+ { TPS_REG_INT_SOURCE_CAP_MESSAGE_READY, "SOURCE_CAP_MESSAGE_READY" }, \
+ { TPS_REG_INT_SINK_CAP_MESSAGE_READY, "SINK_CAP_MESSAGE_READY" }, \
+ { TPS_REG_INT_PR_SWAP_REQUESTED, "PR_SWAP_REQUESTED" }, \
+ { TPS_REG_INT_GOTO_MIN_RECEIVED, "GOTO_MIN_RECEIVED" }, \
+ { TPS_REG_INT_USB_HOST_PRESENT, "USB_HOST_PRESENT" }, \
+ { TPS_REG_INT_USB_HOST_PRESENT_NO_LONGER, "USB_HOST_PRESENT_NO_LONGER" }, \
+ { TPS_REG_INT_HIGH_VOLTAGE_WARNING, "HIGH_VOLTAGE_WARNING" }, \
+ { TPS_REG_INT_PP_SWITCH_CHANGED, "PP_SWITCH_CHANGED" }, \
+ { TPS_REG_INT_POWER_STATUS_UPDATE, "POWER_STATUS_UPDATE" }, \
+ { TPS_REG_INT_DATA_STATUS_UPDATE, "DATA_STATUS_UPDATE" }, \
+ { TPS_REG_INT_STATUS_UPDATE, "STATUS_UPDATE" }, \
+ { TPS_REG_INT_PD_STATUS_UPDATE, "PD_STATUS_UPDATE" }, \
+ { TPS_REG_INT_ADC_LOW_THRESHOLD, "ADC_LOW_THRESHOLD" }, \
+ { TPS_REG_INT_ADC_HIGH_THRESHOLD, "ADC_HIGH_THRESHOLD" }, \
+ { TPS_REG_INT_CMD1_COMPLETE, "CMD1_COMPLETE" }, \
+ { TPS_REG_INT_CMD2_COMPLETE, "CMD2_COMPLETE" }, \
+ { TPS_REG_INT_ERROR_DEVICE_INCOMPATIBLE, "ERROR_DEVICE_INCOMPATIBLE" }, \
+ { TPS_REG_INT_ERROR_CANNOT_PROVIDE_PWR, "ERROR_CANNOT_PROVIDE_PWR" }, \
+ { TPS_REG_INT_ERROR_CAN_PROVIDE_PWR_LATER, "ERROR_CAN_PROVIDE_PWR_LATER" }, \
+ { TPS_REG_INT_ERROR_POWER_EVENT_OCCURRED, "ERROR_POWER_EVENT_OCCURRED" }, \
+ { TPS_REG_INT_ERROR_MISSING_GET_CAP_MESSAGE, "ERROR_MISSING_GET_CAP_MESSAGE" }, \
+ { TPS_REG_INT_ERROR_PROTOCOL_ERROR, "ERROR_PROTOCOL_ERROR" }, \
+ { TPS_REG_INT_ERROR_MESSAGE_DATA, "ERROR_MESSAGE_DATA" }, \
+ { TPS_REG_INT_ERROR_DISCHARGE_FAILED, "ERROR_DISCHARGE_FAILED" }, \
+ { TPS_REG_INT_SRC_TRANSITION, "SRC_TRANSITION" }, \
+ { TPS_REG_INT_ERROR_UNABLE_TO_SOURCE, "ERROR_UNABLE_TO_SOURCE" }, \
+ { TPS_REG_INT_VDM_ENTERED_MODE, "VDM_ENTERED_MODE" }, \
+ { TPS_REG_INT_VDM_MSG_SENT, "VDM_MSG_SENT" }, \
+ { TPS_REG_INT_DISCOVER_MODES_COMPLETE, "DISCOVER_MODES_COMPLETE" }, \
+ { TPS_REG_INT_EXIT_MODES_COMPLETE, "EXIT_MODES_COMPLETE" }, \
+ { TPS_REG_INT_USER_VID_ALT_MODE_ENTERED, "USER_VID_ALT_MODE_ENTERED" }, \
+ { TPS_REG_INT_USER_VID_ALT_MODE_EXIT, "USER_VID_ALT_MODE_EXIT" }, \
+ { TPS_REG_INT_USER_VID_ALT_MODE_ATTN_VDM, "USER_VID_ALT_MODE_ATTN_VDM" }, \
+ { TPS_REG_INT_USER_VID_ALT_MODE_OTHER_VDM, "USER_VID_ALT_MODE_OTHER_VDM" })
+
+#define TPS6598X_STATUS_FLAGS_MASK (GENMASK(31, 0) ^ (TPS_STATUS_CONN_STATE_MASK | \
+ TPS_STATUS_PP_5V0_SWITCH_MASK | \
+ TPS_STATUS_PP_HV_SWITCH_MASK | \
+ TPS_STATUS_PP_EXT_SWITCH_MASK | \
+ TPS_STATUS_PP_CABLE_SWITCH_MASK | \
+ TPS_STATUS_POWER_SOURCE_MASK | \
+ TPS_STATUS_VBUS_STATUS_MASK | \
+ TPS_STATUS_USB_HOST_PRESENT_MASK | \
+ TPS_STATUS_LEGACY_MASK))
+
+#define show_status_conn_state(status) \
+ __print_symbolic(TPS_STATUS_CONN_STATE((status)), \
+ { TPS_STATUS_CONN_STATE_CONN_WITH_R_A, "conn-Ra" }, \
+ { TPS_STATUS_CONN_STATE_CONN_NO_R_A, "conn-no-Ra" }, \
+ { TPS_STATUS_CONN_STATE_NO_CONN_R_A, "no-conn-Ra" }, \
+ { TPS_STATUS_CONN_STATE_DEBUG_CONN, "debug" }, \
+ { TPS_STATUS_CONN_STATE_AUDIO_CONN, "audio" }, \
+ { TPS_STATUS_CONN_STATE_DISABLED, "disabled" }, \
+ { TPS_STATUS_CONN_STATE_NO_CONN, "no-conn" })
+
+#define show_status_pp_switch_state(status) \
+ __print_symbolic(status, \
+ { TPS_STATUS_PP_SWITCH_STATE_IN, "in" }, \
+ { TPS_STATUS_PP_SWITCH_STATE_OUT, "out" }, \
+ { TPS_STATUS_PP_SWITCH_STATE_FAULT, "fault" }, \
+ { TPS_STATUS_PP_SWITCH_STATE_DISABLED, "off" })
+
+#define show_status_power_sources(status) \
+ __print_symbolic(TPS_STATUS_POWER_SOURCE(status), \
+ { TPS_STATUS_POWER_SOURCE_VBUS, "vbus" }, \
+ { TPS_STATUS_POWER_SOURCE_VIN_3P3, "vin-3p3" }, \
+ { TPS_STATUS_POWER_SOURCE_DEAD_BAT, "dead-battery" }, \
+ { TPS_STATUS_POWER_SOURCE_UNKNOWN, "unknown" })
+
+#define show_status_vbus_status(status) \
+ __print_symbolic(TPS_STATUS_VBUS_STATUS(status), \
+ { TPS_STATUS_VBUS_STATUS_VSAFE0V, "vSafe0V" }, \
+ { TPS_STATUS_VBUS_STATUS_VSAFE5V, "vSafe5V" }, \
+ { TPS_STATUS_VBUS_STATUS_PD, "pd" }, \
+ { TPS_STATUS_VBUS_STATUS_FAULT, "fault" })
+
+#define show_status_usb_host_present(status) \
+ __print_symbolic(TPS_STATUS_USB_HOST_PRESENT(status), \
+ { TPS_STATUS_USB_HOST_PRESENT_PD_USB, "pd-usb" }, \
+ { TPS_STATUS_USB_HOST_PRESENT_NO_PD, "no-pd" }, \
+ { TPS_STATUS_USB_HOST_PRESENT_PD_NO_USB, "pd-no-usb" }, \
+ { TPS_STATUS_USB_HOST_PRESENT_NO, "no" })
+
+#define show_status_legacy(status) \
+ __print_symbolic(TPS_STATUS_LEGACY(status), \
+ { TPS_STATUS_LEGACY_SOURCE, "source" }, \
+ { TPS_STATUS_LEGACY_SINK, "sink" }, \
+ { TPS_STATUS_LEGACY_NO, "no" })
+
+#define show_status_flags(flags) \
+ __print_flags((flags & TPS6598X_STATUS_FLAGS_MASK), "|", \
+ { TPS_STATUS_PLUG_PRESENT, "PLUG_PRESENT" }, \
+ { TPS_STATUS_PLUG_UPSIDE_DOWN, "UPSIDE_DOWN" }, \
+ { TPS_STATUS_PORTROLE, "PORTROLE" }, \
+ { TPS_STATUS_DATAROLE, "DATAROLE" }, \
+ { TPS_STATUS_VCONN, "VCONN" }, \
+ { TPS_STATUS_OVERCURRENT, "OVERCURRENT" }, \
+ { TPS_STATUS_GOTO_MIN_ACTIVE, "GOTO_MIN_ACTIVE" }, \
+ { TPS_STATUS_BIST, "BIST" }, \
+ { TPS_STATUS_HIGH_VOLAGE_WARNING, "HIGH_VOLAGE_WARNING" }, \
+ { TPS_STATUS_HIGH_LOW_VOLTAGE_WARNING, "HIGH_LOW_VOLTAGE_WARNING" })
+
+#define show_power_status_source_sink(power_status) \
+ __print_symbolic(TPS_POWER_STATUS_SOURCESINK(power_status), \
+ { 1, "sink" }, \
+ { 0, "source" })
+
+#define show_power_status_typec_status(power_status) \
+ __print_symbolic(TPS_POWER_STATUS_PWROPMODE(power_status), \
+ { TPS_POWER_STATUS_TYPEC_CURRENT_PD, "pd" }, \
+ { TPS_POWER_STATUS_TYPEC_CURRENT_3A0, "3.0A" }, \
+ { TPS_POWER_STATUS_TYPEC_CURRENT_1A5, "1.5A" }, \
+ { TPS_POWER_STATUS_TYPEC_CURRENT_USB, "usb" })
+
+#define show_power_status_bc12_status(power_status) \
+ __print_symbolic(TPS_POWER_STATUS_BC12_STATUS(power_status), \
+ { TPS_POWER_STATUS_BC12_STATUS_DCP, "dcp" }, \
+ { TPS_POWER_STATUS_BC12_STATUS_CDP, "cdp" }, \
+ { TPS_POWER_STATUS_BC12_STATUS_SDP, "sdp" })
+
+#define TPS_DATA_STATUS_FLAGS_MASK (GENMASK(31, 0) ^ (TPS_DATA_STATUS_DP_PIN_ASSIGNMENT_MASK | \
+ TPS_DATA_STATUS_TBT_CABLE_SPEED_MASK | \
+ TPS_DATA_STATUS_TBT_CABLE_GEN_MASK))
+
+#define show_data_status_flags(data_status) \
+ __print_flags(data_status & TPS_DATA_STATUS_FLAGS_MASK, "|", \
+ { TPS_DATA_STATUS_DATA_CONNECTION, "DATA_CONNECTION" }, \
+ { TPS_DATA_STATUS_UPSIDE_DOWN, "DATA_UPSIDE_DOWN" }, \
+ { TPS_DATA_STATUS_ACTIVE_CABLE, "ACTIVE_CABLE" }, \
+ { TPS_DATA_STATUS_USB2_CONNECTION, "USB2_CONNECTION" }, \
+ { TPS_DATA_STATUS_USB3_CONNECTION, "USB3_CONNECTION" }, \
+ { TPS_DATA_STATUS_USB3_GEN2, "USB3_GEN2" }, \
+ { TPS_DATA_STATUS_USB_DATA_ROLE, "USB_DATA_ROLE" }, \
+ { TPS_DATA_STATUS_DP_CONNECTION, "DP_CONNECTION" }, \
+ { TPS_DATA_STATUS_DP_SINK, "DP_SINK" }, \
+ { TPS_DATA_STATUS_TBT_CONNECTION, "TBT_CONNECTION" }, \
+ { TPS_DATA_STATUS_TBT_TYPE, "TBT_TYPE" }, \
+ { TPS_DATA_STATUS_OPTICAL_CABLE, "OPTICAL_CABLE" }, \
+ { TPS_DATA_STATUS_ACTIVE_LINK_TRAIN, "ACTIVE_LINK_TRAIN" }, \
+ { TPS_DATA_STATUS_FORCE_LSX, "FORCE_LSX" }, \
+ { TPS_DATA_STATUS_POWER_MISMATCH, "POWER_MISMATCH" })
+
+#define show_data_status_dp_pin_assignment(data_status) \
+ __print_symbolic(TPS_DATA_STATUS_DP_SPEC_PIN_ASSIGNMENT(data_status), \
+ { TPS_DATA_STATUS_DP_SPEC_PIN_ASSIGNMENT_E, "E" }, \
+ { TPS_DATA_STATUS_DP_SPEC_PIN_ASSIGNMENT_F, "F" }, \
+ { TPS_DATA_STATUS_DP_SPEC_PIN_ASSIGNMENT_C, "C" }, \
+ { TPS_DATA_STATUS_DP_SPEC_PIN_ASSIGNMENT_D, "D" }, \
+ { TPS_DATA_STATUS_DP_SPEC_PIN_ASSIGNMENT_A, "A" }, \
+ { TPS_DATA_STATUS_DP_SPEC_PIN_ASSIGNMENT_B, "B" })
+
+#define maybe_show_data_status_dp_pin_assignment(data_status) \
+ (data_status & TPS_DATA_STATUS_DP_CONNECTION ? \
+ show_data_status_dp_pin_assignment(data_status) : "")
+
+TRACE_EVENT(tps6598x_irq,
+ TP_PROTO(u64 event1,
+ u64 event2),
+ TP_ARGS(event1, event2),
+
+ TP_STRUCT__entry(
+ __field(u64, event1)
+ __field(u64, event2)
+ ),
+
+ TP_fast_assign(
+ __entry->event1 = event1;
+ __entry->event2 = event2;
+ ),
+
+ TP_printk("event1=%s, event2=%s",
+ show_irq_flags(__entry->event1),
+ show_irq_flags(__entry->event2))
+);
+
+TRACE_EVENT(tps6598x_status,
+ TP_PROTO(u32 status),
+ TP_ARGS(status),
+
+ TP_STRUCT__entry(
+ __field(u32, status)
+ ),
+
+ TP_fast_assign(
+ __entry->status = status;
+ ),
+
+ TP_printk("conn: %s, pp_5v0: %s, pp_hv: %s, pp_ext: %s, pp_cable: %s, "
+ "pwr-src: %s, vbus: %s, usb-host: %s, legacy: %s, flags: %s",
+ show_status_conn_state(__entry->status),
+ show_status_pp_switch_state(TPS_STATUS_PP_5V0_SWITCH(__entry->status)),
+ show_status_pp_switch_state(TPS_STATUS_PP_HV_SWITCH(__entry->status)),
+ show_status_pp_switch_state(TPS_STATUS_PP_EXT_SWITCH(__entry->status)),
+ show_status_pp_switch_state(TPS_STATUS_PP_CABLE_SWITCH(__entry->status)),
+ show_status_power_sources(__entry->status),
+ show_status_vbus_status(__entry->status),
+ show_status_usb_host_present(__entry->status),
+ show_status_legacy(__entry->status),
+ show_status_flags(__entry->status)
+ )
+);
+
+TRACE_EVENT(tps6598x_power_status,
+ TP_PROTO(u16 power_status),
+ TP_ARGS(power_status),
+
+ TP_STRUCT__entry(
+ __field(u16, power_status)
+ ),
+
+ TP_fast_assign(
+ __entry->power_status = power_status;
+ ),
+
+ TP_printk("conn: %d, pwr-role: %s, typec: %s, bc: %s",
+ !!TPS_POWER_STATUS_CONNECTION(__entry->power_status),
+ show_power_status_source_sink(__entry->power_status),
+ show_power_status_typec_status(__entry->power_status),
+ show_power_status_bc12_status(__entry->power_status)
+ )
+);
+
+TRACE_EVENT(tps6598x_data_status,
+ TP_PROTO(u32 data_status),
+ TP_ARGS(data_status),
+
+ TP_STRUCT__entry(
+ __field(u32, data_status)
+ ),
+
+ TP_fast_assign(
+ __entry->data_status = data_status;
+ ),
+
+ TP_printk("%s%s%s",
+ show_data_status_flags(__entry->data_status),
+ __entry->data_status & TPS_DATA_STATUS_DP_CONNECTION ? ", DP pinout " : "",
+ maybe_show_data_status_dp_pin_assignment(__entry->data_status)
+ )
+);
+
+#endif /* _TPS6598X_TRACE_H_ */
+
+/* This part must be outside protection */
+#undef TRACE_INCLUDE_FILE
+#define TRACE_INCLUDE_FILE trace
+#undef TRACE_INCLUDE_PATH
+#define TRACE_INCLUDE_PATH .
+#include <trace/define_trace.h>
diff --git a/include/linux/platform_data/usb-mx2.h b/include/linux/platform_data/usb-mx2.h
deleted file mode 100644
index 97a670f3d8fb..000000000000
--- a/include/linux/platform_data/usb-mx2.h
+++ /dev/null
@@ -1,29 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later */
-/*
- * Copyright (C) 2009 Martin Fuzzey <mfuzzey@gmail.com>
- */
-
-#ifndef __ASM_ARCH_MX21_USBH
-#define __ASM_ARCH_MX21_USBH
-
-enum mx21_usbh_xcvr {
- /* Values below as used by hardware (HWMODE register) */
- MX21_USBXCVR_TXDIF_RXDIF = 0,
- MX21_USBXCVR_TXDIF_RXSE = 1,
- MX21_USBXCVR_TXSE_RXDIF = 2,
- MX21_USBXCVR_TXSE_RXSE = 3,
-};
-
-struct mx21_usbh_platform_data {
- enum mx21_usbh_xcvr host_xcvr; /* tranceiver mode host 1,2 ports */
- enum mx21_usbh_xcvr otg_xcvr; /* tranceiver mode otg (as host) port */
- u16 enable_host1:1,
- enable_host2:1,
- enable_otg_host:1, /* enable "OTG" port (as host) */
- host1_xcverless:1, /* traceiverless host1 port */
- host1_txenoe:1, /* output enable host1 transmit enable */
- otg_ext_xcvr:1, /* external tranceiver for OTG port */
- unused:10;
-};
-
-#endif /* __ASM_ARCH_MX21_USBH */
diff --git a/include/linux/usb.h b/include/linux/usb.h
index d6a41841b93e..57c1e0ce5eba 100644
--- a/include/linux/usb.h
+++ b/include/linux/usb.h
@@ -1259,8 +1259,6 @@ struct usb_device_driver {
#define to_usb_device_driver(d) container_of(d, struct usb_device_driver, \
drvwrap.driver)
-extern struct bus_type usb_bus_type;
-
/**
* struct usb_class_driver - identifies a USB driver that wants to use the USB major number
* @name: the usb class device name for this driver. Will show up in sysfs.
diff --git a/include/linux/usb/ch9.h b/include/linux/usb/ch9.h
index abdd310c77f0..1cffa34740b0 100644
--- a/include/linux/usb/ch9.h
+++ b/include/linux/usb/ch9.h
@@ -45,73 +45,15 @@ enum usb_ssp_rate {
USB_SSP_GEN_2x2,
};
-/**
- * usb_ep_type_string() - Returns human readable-name of the endpoint type.
- * @ep_type: The endpoint type to return human-readable name for. If it's not
- * any of the types: USB_ENDPOINT_XFER_{CONTROL, ISOC, BULK, INT},
- * usually got by usb_endpoint_type(), the string 'unknown' will be returned.
- */
extern const char *usb_ep_type_string(int ep_type);
-
-/**
- * usb_speed_string() - Returns human readable-name of the speed.
- * @speed: The speed to return human-readable name for. If it's not
- * any of the speeds defined in usb_device_speed enum, string for
- * USB_SPEED_UNKNOWN will be returned.
- */
extern const char *usb_speed_string(enum usb_device_speed speed);
-
-/**
- * usb_get_maximum_speed - Get maximum requested speed for a given USB
- * controller.
- * @dev: Pointer to the given USB controller device
- *
- * The function gets the maximum speed string from property "maximum-speed",
- * and returns the corresponding enum usb_device_speed.
- */
extern enum usb_device_speed usb_get_maximum_speed(struct device *dev);
-
-/**
- * usb_get_maximum_ssp_rate - Get the signaling rate generation and lane count
- * of a SuperSpeed Plus capable device.
- * @dev: Pointer to the given USB controller device
- *
- * If the string from "maximum-speed" property is super-speed-plus-genXxY where
- * 'X' is the generation number and 'Y' is the number of lanes, then this
- * function returns the corresponding enum usb_ssp_rate.
- */
extern enum usb_ssp_rate usb_get_maximum_ssp_rate(struct device *dev);
-
-/**
- * usb_state_string - Returns human readable name for the state.
- * @state: The state to return a human-readable name for. If it's not
- * any of the states devices in usb_device_state_string enum,
- * the string UNKNOWN will be returned.
- */
extern const char *usb_state_string(enum usb_device_state state);
+unsigned int usb_decode_interval(const struct usb_endpoint_descriptor *epd,
+ enum usb_device_speed speed);
#ifdef CONFIG_TRACING
-/**
- * usb_decode_ctrl - Returns human readable representation of control request.
- * @str: buffer to return a human-readable representation of control request.
- * This buffer should have about 200 bytes.
- * @size: size of str buffer.
- * @bRequestType: matches the USB bmRequestType field
- * @bRequest: matches the USB bRequest field
- * @wValue: matches the USB wValue field (CPU byte order)
- * @wIndex: matches the USB wIndex field (CPU byte order)
- * @wLength: matches the USB wLength field (CPU byte order)
- *
- * Function returns decoded, formatted and human-readable description of
- * control request packet.
- *
- * The usage scenario for this is for tracepoints, so function as a return
- * use the same value as in parameters. This approach allows to use this
- * function in TP_printk
- *
- * Important: wValue, wIndex, wLength parameters before invoking this function
- * should be processed by le16_to_cpu macro.
- */
extern const char *usb_decode_ctrl(char *str, size_t size, __u8 bRequestType,
__u8 bRequest, __u16 wValue, __u16 wIndex,
__u16 wLength);