USB fixes for 5.13-rc6
Here are a number of tiny USB fixes for 5.13-rc6. There are more than I would normally like, but there's been a bunch of people banging on the gadget and dwc3 and typec code recently for I think an Android release, which has resulted in a number of small fixes. It's nice to see companies send fixes upstream for this type of work, a notable change from years ago. Anyway, fixes in here are: - usb-serial device id updates - usb-serial cp210x driver fixes for broken firmware versions - typec fixes for crazy charging devices and other reported problems - dwc3 fixes for reported problems found - gadget fixes for reported problems - tiny xhci fixes - other small fixes for reported issues. - revert of a problem fix found by linux-next testing All of these have passed 0-day and linux-next testing with no reported problems (the revert for the found linux-next build problem included). Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> -----BEGIN PGP SIGNATURE----- iG0EABECAC0WIQT0tgzFv3jCIUoxPcsxR9QN2y37KQUCYMS6uA8cZ3JlZ0Brcm9h aC5jb20ACgkQMUfUDdst+yknTgCeKSmtJABTIcZ3LLRgArqUFEroUqEAni2ZRv/8 3mGzeXFKvvoEO/WoILmV =WqGE -----END PGP SIGNATURE----- Merge tag 'usb-5.13-rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb Pull USB fixes from Greg KH: "Here are a number of tiny USB fixes for 5.13-rc6. There are more than I would normally like, but there's been a bunch of people banging on the gadget and dwc3 and typec code recently for I think an Android release, which has resulted in a number of small fixes. It's nice to see companies send fixes upstream for this type of work, a notable change from years ago. Anyway, fixes in here are: - usb-serial device id updates - usb-serial cp210x driver fixes for broken firmware versions - typec fixes for crazy charging devices and other reported problems - dwc3 fixes for reported problems found - gadget fixes for reported problems - tiny xhci fixes - other small fixes for reported issues. - revert of a problem fix found by linux-next testing All of these have passed 0-day and linux-next testing with no reported problems (the revert for the found linux-next build problem included)" * tag 'usb-5.13-rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb: (44 commits) Revert "usb: gadget: fsl: Re-enable driver for ARM SoCs" usb: typec: mux: Fix copy-paste mistake in typec_mux_match usb: typec: ucsi: Clear PPM capability data in ucsi_init() error path usb: gadget: fsl: Re-enable driver for ARM SoCs usb: typec: wcove: Use LE to CPU conversion when accessing msg->header USB: serial: cp210x: fix CP2102N-A01 modem control USB: serial: cp210x: fix alternate function for CP2102N QFN20 usb: misc: brcmstb-usb-pinmap: check return value after calling platform_get_resource() usb: dwc3: ep0: fix NULL pointer exception usb: gadget: eem: fix wrong eem header operation usb: typec: intel_pmc_mux: Put ACPI device using acpi_dev_put() usb: typec: intel_pmc_mux: Add missed error check for devm_ioremap_resource() usb: typec: intel_pmc_mux: Put fwnode in error case during ->probe() usb: typec: tcpm: Do not finish VDM AMS for retrying Responses usb: fix various gadget panics on 10gbps cabling usb: fix various gadgets null ptr deref on 10gbps cabling. usb: pci-quirks: disable D3cold on xhci suspend for s2idle on AMD Renoir usb: f_ncm: only first packet of aggregate needs to start timer USB: f_ncm: ncm_bitrate (speed) is unsigned MAINTAINERS: usb: add entry for isp1760 ...
This commit is contained in:
commit
43cb5d49a9
|
@ -149,6 +149,17 @@ properties:
|
|||
maxItems: 6
|
||||
$ref: /schemas/types.yaml#/definitions/uint32-array
|
||||
|
||||
sink-vdos-v1:
|
||||
description: An array of u32 with each entry, a Vendor Defined Message Object (VDO),
|
||||
providing additional information corresponding to the product, the detailed bit
|
||||
definitions and the order of each VDO can be found in
|
||||
"USB Power Delivery Specification Revision 2.0, Version 1.3" chapter 6.4.4.3.1 Discover
|
||||
Identity. User can specify the VDO array via VDO_IDH/_CERT/_PRODUCT/_CABLE/_AMA defined in
|
||||
dt-bindings/usb/pd.h.
|
||||
minItems: 3
|
||||
maxItems: 6
|
||||
$ref: /schemas/types.yaml#/definitions/uint32-array
|
||||
|
||||
op-sink-microwatt:
|
||||
description: Sink required operating power in microwatt, if source can't
|
||||
offer the power, Capability Mismatch is set. Required for power sink and
|
||||
|
@ -207,6 +218,10 @@ properties:
|
|||
SNK_READY for non-pd link.
|
||||
type: boolean
|
||||
|
||||
dependencies:
|
||||
sink-vdos-v1: [ 'sink-vdos' ]
|
||||
sink-vdos: [ 'sink-vdos-v1' ]
|
||||
|
||||
required:
|
||||
- compatible
|
||||
|
||||
|
|
|
@ -18873,6 +18873,13 @@ S: Maintained
|
|||
F: drivers/usb/host/isp116x*
|
||||
F: include/linux/usb/isp116x.h
|
||||
|
||||
USB ISP1760 DRIVER
|
||||
M: Rui Miguel Silva <rui.silva@linaro.org>
|
||||
L: linux-usb@vger.kernel.org
|
||||
S: Maintained
|
||||
F: drivers/usb/isp1760/*
|
||||
F: Documentation/devicetree/bindings/usb/nxp,isp1760.yaml
|
||||
|
||||
USB LAN78XX ETHERNET DRIVER
|
||||
M: Woojung Huh <woojung.huh@microchip.com>
|
||||
M: UNGLinuxDriver@microchip.com
|
||||
|
|
|
@ -2007,7 +2007,7 @@ static void cdns3_configure_dmult(struct cdns3_device *priv_dev,
|
|||
else
|
||||
mask = BIT(priv_ep->num);
|
||||
|
||||
if (priv_ep->type != USB_ENDPOINT_XFER_ISOC) {
|
||||
if (priv_ep->type != USB_ENDPOINT_XFER_ISOC && !priv_ep->dir) {
|
||||
cdns3_set_register_bit(®s->tdl_from_trb, mask);
|
||||
cdns3_set_register_bit(®s->tdl_beh, mask);
|
||||
cdns3_set_register_bit(®s->tdl_beh2, mask);
|
||||
|
@ -2046,15 +2046,13 @@ int cdns3_ep_config(struct cdns3_endpoint *priv_ep, bool enable)
|
|||
case USB_ENDPOINT_XFER_INT:
|
||||
ep_cfg = EP_CFG_EPTYPE(USB_ENDPOINT_XFER_INT);
|
||||
|
||||
if ((priv_dev->dev_ver == DEV_VER_V2 && !priv_ep->dir) ||
|
||||
priv_dev->dev_ver > DEV_VER_V2)
|
||||
if (priv_dev->dev_ver >= DEV_VER_V2 && !priv_ep->dir)
|
||||
ep_cfg |= EP_CFG_TDL_CHK;
|
||||
break;
|
||||
case USB_ENDPOINT_XFER_BULK:
|
||||
ep_cfg = EP_CFG_EPTYPE(USB_ENDPOINT_XFER_BULK);
|
||||
|
||||
if ((priv_dev->dev_ver == DEV_VER_V2 && !priv_ep->dir) ||
|
||||
priv_dev->dev_ver > DEV_VER_V2)
|
||||
if (priv_dev->dev_ver >= DEV_VER_V2 && !priv_ep->dir)
|
||||
ep_cfg |= EP_CFG_TDL_CHK;
|
||||
break;
|
||||
default:
|
||||
|
|
|
@ -1517,13 +1517,14 @@ irqreturn_t cdnsp_thread_irq_handler(int irq, void *data)
|
|||
{
|
||||
struct cdnsp_device *pdev = (struct cdnsp_device *)data;
|
||||
union cdnsp_trb *event_ring_deq;
|
||||
unsigned long flags;
|
||||
int counter = 0;
|
||||
|
||||
spin_lock(&pdev->lock);
|
||||
spin_lock_irqsave(&pdev->lock, flags);
|
||||
|
||||
if (pdev->cdnsp_state & (CDNSP_STATE_HALTED | CDNSP_STATE_DYING)) {
|
||||
cdnsp_died(pdev);
|
||||
spin_unlock(&pdev->lock);
|
||||
spin_unlock_irqrestore(&pdev->lock, flags);
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
|
@ -1539,7 +1540,7 @@ irqreturn_t cdnsp_thread_irq_handler(int irq, void *data)
|
|||
|
||||
cdnsp_update_erst_dequeue(pdev, event_ring_deq, 1);
|
||||
|
||||
spin_unlock(&pdev->lock);
|
||||
spin_unlock_irqrestore(&pdev->lock, flags);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
|
|
@ -1690,11 +1690,6 @@ static int dwc3_remove(struct platform_device *pdev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void dwc3_shutdown(struct platform_device *pdev)
|
||||
{
|
||||
dwc3_remove(pdev);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
static int dwc3_core_init_for_resume(struct dwc3 *dwc)
|
||||
{
|
||||
|
@ -2012,7 +2007,6 @@ MODULE_DEVICE_TABLE(acpi, dwc3_acpi_match);
|
|||
static struct platform_driver dwc3_driver = {
|
||||
.probe = dwc3_probe,
|
||||
.remove = dwc3_remove,
|
||||
.shutdown = dwc3_shutdown,
|
||||
.driver = {
|
||||
.name = "dwc3",
|
||||
.of_match_table = of_match_ptr(of_dwc3_match),
|
||||
|
|
|
@ -413,9 +413,12 @@ static inline const char *dwc3_gadget_generic_cmd_status_string(int status)
|
|||
|
||||
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
extern void dwc3_debugfs_create_endpoint_dir(struct dwc3_ep *dep);
|
||||
extern void dwc3_debugfs_init(struct dwc3 *d);
|
||||
extern void dwc3_debugfs_exit(struct dwc3 *d);
|
||||
#else
|
||||
static inline void dwc3_debugfs_create_endpoint_dir(struct dwc3_ep *dep)
|
||||
{ }
|
||||
static inline void dwc3_debugfs_init(struct dwc3 *d)
|
||||
{ }
|
||||
static inline void dwc3_debugfs_exit(struct dwc3 *d)
|
||||
|
|
|
@ -886,30 +886,14 @@ static void dwc3_debugfs_create_endpoint_files(struct dwc3_ep *dep,
|
|||
}
|
||||
}
|
||||
|
||||
static void dwc3_debugfs_create_endpoint_dir(struct dwc3_ep *dep,
|
||||
struct dentry *parent)
|
||||
void dwc3_debugfs_create_endpoint_dir(struct dwc3_ep *dep)
|
||||
{
|
||||
struct dentry *dir;
|
||||
|
||||
dir = debugfs_create_dir(dep->name, parent);
|
||||
dir = debugfs_create_dir(dep->name, dep->dwc->root);
|
||||
dwc3_debugfs_create_endpoint_files(dep, dir);
|
||||
}
|
||||
|
||||
static void dwc3_debugfs_create_endpoint_dirs(struct dwc3 *dwc,
|
||||
struct dentry *parent)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < dwc->num_eps; i++) {
|
||||
struct dwc3_ep *dep = dwc->eps[i];
|
||||
|
||||
if (!dep)
|
||||
continue;
|
||||
|
||||
dwc3_debugfs_create_endpoint_dir(dep, parent);
|
||||
}
|
||||
}
|
||||
|
||||
void dwc3_debugfs_init(struct dwc3 *dwc)
|
||||
{
|
||||
struct dentry *root;
|
||||
|
@ -940,7 +924,6 @@ void dwc3_debugfs_init(struct dwc3 *dwc)
|
|||
&dwc3_testmode_fops);
|
||||
debugfs_create_file("link_state", 0644, root, dwc,
|
||||
&dwc3_link_state_fops);
|
||||
dwc3_debugfs_create_endpoint_dirs(dwc, root);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -651,7 +651,7 @@ static int dwc3_meson_g12a_setup_regmaps(struct dwc3_meson_g12a *priv,
|
|||
return PTR_ERR(priv->usb_glue_regmap);
|
||||
|
||||
/* Create a regmap for each USB2 PHY control register set */
|
||||
for (i = 0; i < priv->usb2_ports; i++) {
|
||||
for (i = 0; i < priv->drvdata->num_phys; i++) {
|
||||
struct regmap_config u2p_regmap_config = {
|
||||
.reg_bits = 8,
|
||||
.val_bits = 32,
|
||||
|
@ -659,6 +659,9 @@ static int dwc3_meson_g12a_setup_regmaps(struct dwc3_meson_g12a *priv,
|
|||
.max_register = U2P_R1,
|
||||
};
|
||||
|
||||
if (!strstr(priv->drvdata->phy_names[i], "usb2"))
|
||||
continue;
|
||||
|
||||
u2p_regmap_config.name = devm_kasprintf(priv->dev, GFP_KERNEL,
|
||||
"u2p-%d", i);
|
||||
if (!u2p_regmap_config.name)
|
||||
|
@ -772,13 +775,13 @@ static int dwc3_meson_g12a_probe(struct platform_device *pdev)
|
|||
|
||||
ret = priv->drvdata->usb_init(priv);
|
||||
if (ret)
|
||||
goto err_disable_clks;
|
||||
goto err_disable_regulator;
|
||||
|
||||
/* Init PHYs */
|
||||
for (i = 0 ; i < PHY_COUNT ; ++i) {
|
||||
ret = phy_init(priv->phys[i]);
|
||||
if (ret)
|
||||
goto err_disable_clks;
|
||||
goto err_disable_regulator;
|
||||
}
|
||||
|
||||
/* Set PHY Power */
|
||||
|
@ -816,6 +819,10 @@ err_phys_exit:
|
|||
for (i = 0 ; i < PHY_COUNT ; ++i)
|
||||
phy_exit(priv->phys[i]);
|
||||
|
||||
err_disable_regulator:
|
||||
if (priv->vbus)
|
||||
regulator_disable(priv->vbus);
|
||||
|
||||
err_disable_clks:
|
||||
clk_bulk_disable_unprepare(priv->drvdata->num_clks,
|
||||
priv->drvdata->clks);
|
||||
|
|
|
@ -292,6 +292,9 @@ static struct dwc3_ep *dwc3_wIndex_to_dep(struct dwc3 *dwc, __le16 wIndex_le)
|
|||
epnum |= 1;
|
||||
|
||||
dep = dwc->eps[epnum];
|
||||
if (dep == NULL)
|
||||
return NULL;
|
||||
|
||||
if (dep->flags & DWC3_EP_ENABLED)
|
||||
return dep;
|
||||
|
||||
|
|
|
@ -2261,13 +2261,10 @@ static int dwc3_gadget_pullup(struct usb_gadget *g, int is_on)
|
|||
}
|
||||
|
||||
/*
|
||||
* Synchronize any pending event handling before executing the controller
|
||||
* halt routine.
|
||||
* Synchronize and disable any further event handling while controller
|
||||
* is being enabled/disabled.
|
||||
*/
|
||||
if (!is_on) {
|
||||
dwc3_gadget_disable_irq(dwc);
|
||||
synchronize_irq(dwc->irq_gadget);
|
||||
}
|
||||
disable_irq(dwc->irq_gadget);
|
||||
|
||||
spin_lock_irqsave(&dwc->lock, flags);
|
||||
|
||||
|
@ -2305,6 +2302,8 @@ static int dwc3_gadget_pullup(struct usb_gadget *g, int is_on)
|
|||
|
||||
ret = dwc3_gadget_run_stop(dwc, is_on, false);
|
||||
spin_unlock_irqrestore(&dwc->lock, flags);
|
||||
enable_irq(dwc->irq_gadget);
|
||||
|
||||
pm_runtime_put(dwc->dev);
|
||||
|
||||
return ret;
|
||||
|
@ -2754,6 +2753,8 @@ static int dwc3_gadget_init_endpoint(struct dwc3 *dwc, u8 epnum)
|
|||
INIT_LIST_HEAD(&dep->started_list);
|
||||
INIT_LIST_HEAD(&dep->cancelled_list);
|
||||
|
||||
dwc3_debugfs_create_endpoint_dir(dep);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -2797,6 +2798,7 @@ static void dwc3_gadget_free_endpoints(struct dwc3 *dwc)
|
|||
list_del(&dep->endpoint.ep_list);
|
||||
}
|
||||
|
||||
debugfs_remove_recursive(debugfs_lookup(dep->name, dwc->root));
|
||||
kfree(dep);
|
||||
}
|
||||
}
|
||||
|
@ -4046,6 +4048,7 @@ err5:
|
|||
dwc3_gadget_free_endpoints(dwc);
|
||||
err4:
|
||||
usb_put_gadget(dwc->gadget);
|
||||
dwc->gadget = NULL;
|
||||
err3:
|
||||
dma_free_coherent(dwc->sysdev, DWC3_BOUNCE_SIZE, dwc->bounce,
|
||||
dwc->bounce_addr);
|
||||
|
@ -4065,6 +4068,9 @@ err0:
|
|||
|
||||
void dwc3_gadget_exit(struct dwc3 *dwc)
|
||||
{
|
||||
if (!dwc->gadget)
|
||||
return;
|
||||
|
||||
usb_del_gadget(dwc->gadget);
|
||||
dwc3_gadget_free_endpoints(dwc);
|
||||
usb_put_gadget(dwc->gadget);
|
||||
|
|
|
@ -164,6 +164,14 @@ int usb_assign_descriptors(struct usb_function *f,
|
|||
{
|
||||
struct usb_gadget *g = f->config->cdev->gadget;
|
||||
|
||||
/* super-speed-plus descriptor falls back to super-speed one,
|
||||
* if such a descriptor was provided, thus avoiding a NULL
|
||||
* pointer dereference if a 5gbps capable gadget is used with
|
||||
* a 10gbps capable config (device port + cable + host port)
|
||||
*/
|
||||
if (!ssp)
|
||||
ssp = ss;
|
||||
|
||||
if (fs) {
|
||||
f->fs_descriptors = usb_copy_descriptors(fs);
|
||||
if (!f->fs_descriptors)
|
||||
|
|
|
@ -791,7 +791,7 @@ ecm_bind(struct usb_configuration *c, struct usb_function *f)
|
|||
fs_ecm_notify_desc.bEndpointAddress;
|
||||
|
||||
status = usb_assign_descriptors(f, ecm_fs_function, ecm_hs_function,
|
||||
ecm_ss_function, NULL);
|
||||
ecm_ss_function, ecm_ss_function);
|
||||
if (status)
|
||||
goto fail;
|
||||
|
||||
|
|
|
@ -302,7 +302,7 @@ static int eem_bind(struct usb_configuration *c, struct usb_function *f)
|
|||
eem_ss_out_desc.bEndpointAddress = eem_fs_out_desc.bEndpointAddress;
|
||||
|
||||
status = usb_assign_descriptors(f, eem_fs_function, eem_hs_function,
|
||||
eem_ss_function, NULL);
|
||||
eem_ss_function, eem_ss_function);
|
||||
if (status)
|
||||
goto fail;
|
||||
|
||||
|
@ -495,7 +495,7 @@ static int eem_unwrap(struct gether *port,
|
|||
skb2 = skb_clone(skb, GFP_ATOMIC);
|
||||
if (unlikely(!skb2)) {
|
||||
DBG(cdev, "unable to unframe EEM packet\n");
|
||||
continue;
|
||||
goto next;
|
||||
}
|
||||
skb_trim(skb2, len - ETH_FCS_LEN);
|
||||
|
||||
|
@ -505,7 +505,7 @@ static int eem_unwrap(struct gether *port,
|
|||
GFP_ATOMIC);
|
||||
if (unlikely(!skb3)) {
|
||||
dev_kfree_skb_any(skb2);
|
||||
continue;
|
||||
goto next;
|
||||
}
|
||||
dev_kfree_skb_any(skb2);
|
||||
skb_queue_tail(list, skb3);
|
||||
|
|
|
@ -3567,6 +3567,9 @@ static void ffs_func_unbind(struct usb_configuration *c,
|
|||
ffs->func = NULL;
|
||||
}
|
||||
|
||||
/* Drain any pending AIO completions */
|
||||
drain_workqueue(ffs->io_completion_wq);
|
||||
|
||||
if (!--opts->refcnt)
|
||||
functionfs_unbind(ffs);
|
||||
|
||||
|
|
|
@ -802,7 +802,8 @@ static int hidg_bind(struct usb_configuration *c, struct usb_function *f)
|
|||
hidg_fs_out_ep_desc.bEndpointAddress;
|
||||
|
||||
status = usb_assign_descriptors(f, hidg_fs_descriptors,
|
||||
hidg_hs_descriptors, hidg_ss_descriptors, NULL);
|
||||
hidg_hs_descriptors, hidg_ss_descriptors,
|
||||
hidg_ss_descriptors);
|
||||
if (status)
|
||||
goto fail;
|
||||
|
||||
|
|
|
@ -207,7 +207,7 @@ autoconf_fail:
|
|||
ss_loop_sink_desc.bEndpointAddress = fs_loop_sink_desc.bEndpointAddress;
|
||||
|
||||
ret = usb_assign_descriptors(f, fs_loopback_descs, hs_loopback_descs,
|
||||
ss_loopback_descs, NULL);
|
||||
ss_loopback_descs, ss_loopback_descs);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
|
|
|
@ -583,7 +583,7 @@ static void ncm_do_notify(struct f_ncm *ncm)
|
|||
data[0] = cpu_to_le32(ncm_bitrate(cdev->gadget));
|
||||
data[1] = data[0];
|
||||
|
||||
DBG(cdev, "notify speed %d\n", ncm_bitrate(cdev->gadget));
|
||||
DBG(cdev, "notify speed %u\n", ncm_bitrate(cdev->gadget));
|
||||
ncm->notify_state = NCM_NOTIFY_CONNECT;
|
||||
break;
|
||||
}
|
||||
|
@ -1101,11 +1101,11 @@ static struct sk_buff *ncm_wrap_ntb(struct gether *port,
|
|||
ncm->ndp_dgram_count = 1;
|
||||
|
||||
/* Note: we skip opts->next_ndp_index */
|
||||
}
|
||||
|
||||
/* Delay the timer. */
|
||||
/* Start the timer. */
|
||||
hrtimer_start(&ncm->task_timer, TX_TIMEOUT_NSECS,
|
||||
HRTIMER_MODE_REL_SOFT);
|
||||
}
|
||||
|
||||
/* Add the datagram position entries */
|
||||
ntb_ndp = skb_put_zero(ncm->skb_tx_ndp, dgram_idx_len);
|
||||
|
|
|
@ -1101,7 +1101,8 @@ autoconf_fail:
|
|||
ss_ep_out_desc.bEndpointAddress = fs_ep_out_desc.bEndpointAddress;
|
||||
|
||||
ret = usb_assign_descriptors(f, fs_printer_function,
|
||||
hs_printer_function, ss_printer_function, NULL);
|
||||
hs_printer_function, ss_printer_function,
|
||||
ss_printer_function);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
|
|
|
@ -789,7 +789,7 @@ rndis_bind(struct usb_configuration *c, struct usb_function *f)
|
|||
ss_notify_desc.bEndpointAddress = fs_notify_desc.bEndpointAddress;
|
||||
|
||||
status = usb_assign_descriptors(f, eth_fs_function, eth_hs_function,
|
||||
eth_ss_function, NULL);
|
||||
eth_ss_function, eth_ss_function);
|
||||
if (status)
|
||||
goto fail;
|
||||
|
||||
|
|
|
@ -233,7 +233,7 @@ static int gser_bind(struct usb_configuration *c, struct usb_function *f)
|
|||
gser_ss_out_desc.bEndpointAddress = gser_fs_out_desc.bEndpointAddress;
|
||||
|
||||
status = usb_assign_descriptors(f, gser_fs_function, gser_hs_function,
|
||||
gser_ss_function, NULL);
|
||||
gser_ss_function, gser_ss_function);
|
||||
if (status)
|
||||
goto fail;
|
||||
dev_dbg(&cdev->gadget->dev, "generic ttyGS%d: %s speed IN/%s OUT/%s\n",
|
||||
|
|
|
@ -431,7 +431,8 @@ no_iso:
|
|||
ss_iso_sink_desc.bEndpointAddress = fs_iso_sink_desc.bEndpointAddress;
|
||||
|
||||
ret = usb_assign_descriptors(f, fs_source_sink_descs,
|
||||
hs_source_sink_descs, ss_source_sink_descs, NULL);
|
||||
hs_source_sink_descs, ss_source_sink_descs,
|
||||
ss_source_sink_descs);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
|
|
|
@ -358,7 +358,7 @@ geth_bind(struct usb_configuration *c, struct usb_function *f)
|
|||
fs_subset_out_desc.bEndpointAddress;
|
||||
|
||||
status = usb_assign_descriptors(f, fs_eth_function, hs_eth_function,
|
||||
ss_eth_function, NULL);
|
||||
ss_eth_function, ss_eth_function);
|
||||
if (status)
|
||||
goto fail;
|
||||
|
||||
|
|
|
@ -2057,7 +2057,8 @@ static int tcm_bind(struct usb_configuration *c, struct usb_function *f)
|
|||
uasp_fs_cmd_desc.bEndpointAddress = uasp_ss_cmd_desc.bEndpointAddress;
|
||||
|
||||
ret = usb_assign_descriptors(f, uasp_fs_function_desc,
|
||||
uasp_hs_function_desc, uasp_ss_function_desc, NULL);
|
||||
uasp_hs_function_desc, uasp_ss_function_desc,
|
||||
uasp_ss_function_desc);
|
||||
if (ret)
|
||||
goto ep_fail;
|
||||
|
||||
|
|
|
@ -59,6 +59,7 @@
|
|||
#define PCI_DEVICE_ID_INTEL_MAPLE_RIDGE_XHCI 0x1138
|
||||
#define PCI_DEVICE_ID_INTEL_ALDER_LAKE_XHCI 0x461e
|
||||
|
||||
#define PCI_DEVICE_ID_AMD_RENOIR_XHCI 0x1639
|
||||
#define PCI_DEVICE_ID_AMD_PROMONTORYA_4 0x43b9
|
||||
#define PCI_DEVICE_ID_AMD_PROMONTORYA_3 0x43ba
|
||||
#define PCI_DEVICE_ID_AMD_PROMONTORYA_2 0x43bb
|
||||
|
@ -182,6 +183,10 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci)
|
|||
(pdev->device == PCI_DEVICE_ID_AMD_PROMONTORYA_1)))
|
||||
xhci->quirks |= XHCI_U2_DISABLE_WAKE;
|
||||
|
||||
if (pdev->vendor == PCI_VENDOR_ID_AMD &&
|
||||
pdev->device == PCI_DEVICE_ID_AMD_RENOIR_XHCI)
|
||||
xhci->quirks |= XHCI_BROKEN_D3COLD;
|
||||
|
||||
if (pdev->vendor == PCI_VENDOR_ID_INTEL) {
|
||||
xhci->quirks |= XHCI_LPM_SUPPORT;
|
||||
xhci->quirks |= XHCI_INTEL_HOST;
|
||||
|
@ -539,7 +544,7 @@ static int xhci_pci_suspend(struct usb_hcd *hcd, bool do_wakeup)
|
|||
* Systems with the TI redriver that loses port status change events
|
||||
* need to have the registers polled during D3, so avoid D3cold.
|
||||
*/
|
||||
if (xhci->quirks & XHCI_COMP_MODE_QUIRK)
|
||||
if (xhci->quirks & (XHCI_COMP_MODE_QUIRK | XHCI_BROKEN_D3COLD))
|
||||
pci_d3cold_disable(pdev);
|
||||
|
||||
if (xhci->quirks & XHCI_PME_STUCK_QUIRK)
|
||||
|
|
|
@ -1892,6 +1892,7 @@ struct xhci_hcd {
|
|||
#define XHCI_DISABLE_SPARSE BIT_ULL(38)
|
||||
#define XHCI_SG_TRB_CACHE_SIZE_QUIRK BIT_ULL(39)
|
||||
#define XHCI_NO_SOFT_RETRY BIT_ULL(40)
|
||||
#define XHCI_BROKEN_D3COLD BIT_ULL(41)
|
||||
|
||||
unsigned int num_active_eps;
|
||||
unsigned int limit_active_eps;
|
||||
|
|
|
@ -263,6 +263,8 @@ static int __init brcmstb_usb_pinmap_probe(struct platform_device *pdev)
|
|||
return -EINVAL;
|
||||
|
||||
r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
if (!r)
|
||||
return -EINVAL;
|
||||
|
||||
pdata = devm_kzalloc(&pdev->dev,
|
||||
sizeof(*pdata) +
|
||||
|
|
|
@ -2009,9 +2009,8 @@ static void musb_pm_runtime_check_session(struct musb *musb)
|
|||
schedule_delayed_work(&musb->irq_work,
|
||||
msecs_to_jiffies(1000));
|
||||
musb->quirk_retries--;
|
||||
break;
|
||||
}
|
||||
fallthrough;
|
||||
break;
|
||||
case MUSB_QUIRK_B_INVALID_VBUS_91:
|
||||
if (musb->quirk_retries && !musb->flush_irq_work) {
|
||||
musb_dbg(musb,
|
||||
|
|
|
@ -252,9 +252,11 @@ struct cp210x_serial_private {
|
|||
u8 gpio_input;
|
||||
#endif
|
||||
u8 partnum;
|
||||
u32 fw_version;
|
||||
speed_t min_speed;
|
||||
speed_t max_speed;
|
||||
bool use_actual_rate;
|
||||
bool no_flow_control;
|
||||
};
|
||||
|
||||
enum cp210x_event_state {
|
||||
|
@ -398,6 +400,7 @@ struct cp210x_special_chars {
|
|||
|
||||
/* CP210X_VENDOR_SPECIFIC values */
|
||||
#define CP210X_READ_2NCONFIG 0x000E
|
||||
#define CP210X_GET_FW_VER_2N 0x0010
|
||||
#define CP210X_READ_LATCH 0x00C2
|
||||
#define CP210X_GET_PARTNUM 0x370B
|
||||
#define CP210X_GET_PORTCONFIG 0x370C
|
||||
|
@ -537,6 +540,12 @@ struct cp210x_single_port_config {
|
|||
#define CP210X_2NCONFIG_GPIO_RSTLATCH_IDX 587
|
||||
#define CP210X_2NCONFIG_GPIO_CONTROL_IDX 600
|
||||
|
||||
/* CP2102N QFN20 port configuration values */
|
||||
#define CP2102N_QFN20_GPIO2_TXLED_MODE BIT(2)
|
||||
#define CP2102N_QFN20_GPIO3_RXLED_MODE BIT(3)
|
||||
#define CP2102N_QFN20_GPIO1_RS485_MODE BIT(4)
|
||||
#define CP2102N_QFN20_GPIO0_CLK_MODE BIT(6)
|
||||
|
||||
/* CP210X_VENDOR_SPECIFIC, CP210X_WRITE_LATCH call writes these 0x2 bytes. */
|
||||
struct cp210x_gpio_write {
|
||||
u8 mask;
|
||||
|
@ -1122,6 +1131,7 @@ static bool cp210x_termios_change(const struct ktermios *a, const struct ktermio
|
|||
static void cp210x_set_flow_control(struct tty_struct *tty,
|
||||
struct usb_serial_port *port, struct ktermios *old_termios)
|
||||
{
|
||||
struct cp210x_serial_private *priv = usb_get_serial_data(port->serial);
|
||||
struct cp210x_port_private *port_priv = usb_get_serial_port_data(port);
|
||||
struct cp210x_special_chars chars;
|
||||
struct cp210x_flow_ctl flow_ctl;
|
||||
|
@ -1129,6 +1139,15 @@ static void cp210x_set_flow_control(struct tty_struct *tty,
|
|||
u32 ctl_hs;
|
||||
int ret;
|
||||
|
||||
/*
|
||||
* Some CP2102N interpret ulXonLimit as ulFlowReplace (erratum
|
||||
* CP2102N_E104). Report back that flow control is not supported.
|
||||
*/
|
||||
if (priv->no_flow_control) {
|
||||
tty->termios.c_cflag &= ~CRTSCTS;
|
||||
tty->termios.c_iflag &= ~(IXON | IXOFF);
|
||||
}
|
||||
|
||||
if (old_termios &&
|
||||
C_CRTSCTS(tty) == (old_termios->c_cflag & CRTSCTS) &&
|
||||
I_IXON(tty) == (old_termios->c_iflag & IXON) &&
|
||||
|
@ -1185,19 +1204,20 @@ static void cp210x_set_flow_control(struct tty_struct *tty,
|
|||
port_priv->crtscts = false;
|
||||
}
|
||||
|
||||
if (I_IXOFF(tty))
|
||||
if (I_IXOFF(tty)) {
|
||||
flow_repl |= CP210X_SERIAL_AUTO_RECEIVE;
|
||||
else
|
||||
|
||||
flow_ctl.ulXonLimit = cpu_to_le32(128);
|
||||
flow_ctl.ulXoffLimit = cpu_to_le32(128);
|
||||
} else {
|
||||
flow_repl &= ~CP210X_SERIAL_AUTO_RECEIVE;
|
||||
}
|
||||
|
||||
if (I_IXON(tty))
|
||||
flow_repl |= CP210X_SERIAL_AUTO_TRANSMIT;
|
||||
else
|
||||
flow_repl &= ~CP210X_SERIAL_AUTO_TRANSMIT;
|
||||
|
||||
flow_ctl.ulXonLimit = cpu_to_le32(128);
|
||||
flow_ctl.ulXoffLimit = cpu_to_le32(128);
|
||||
|
||||
dev_dbg(&port->dev, "%s - ctrl = 0x%02x, flow = 0x%02x\n", __func__,
|
||||
ctl_hs, flow_repl);
|
||||
|
||||
|
@ -1733,7 +1753,19 @@ static int cp2102n_gpioconf_init(struct usb_serial *serial)
|
|||
priv->gpio_pushpull = (gpio_pushpull >> 3) & 0x0f;
|
||||
|
||||
/* 0 indicates GPIO mode, 1 is alternate function */
|
||||
if (priv->partnum == CP210X_PARTNUM_CP2102N_QFN20) {
|
||||
/* QFN20 is special... */
|
||||
if (gpio_ctrl & CP2102N_QFN20_GPIO0_CLK_MODE) /* GPIO 0 */
|
||||
priv->gpio_altfunc |= BIT(0);
|
||||
if (gpio_ctrl & CP2102N_QFN20_GPIO1_RS485_MODE) /* GPIO 1 */
|
||||
priv->gpio_altfunc |= BIT(1);
|
||||
if (gpio_ctrl & CP2102N_QFN20_GPIO2_TXLED_MODE) /* GPIO 2 */
|
||||
priv->gpio_altfunc |= BIT(2);
|
||||
if (gpio_ctrl & CP2102N_QFN20_GPIO3_RXLED_MODE) /* GPIO 3 */
|
||||
priv->gpio_altfunc |= BIT(3);
|
||||
} else {
|
||||
priv->gpio_altfunc = (gpio_ctrl >> 2) & 0x0f;
|
||||
}
|
||||
|
||||
if (priv->partnum == CP210X_PARTNUM_CP2102N_QFN28) {
|
||||
/*
|
||||
|
@ -1908,6 +1940,45 @@ static void cp210x_init_max_speed(struct usb_serial *serial)
|
|||
priv->use_actual_rate = use_actual_rate;
|
||||
}
|
||||
|
||||
static int cp210x_get_fw_version(struct usb_serial *serial, u16 value)
|
||||
{
|
||||
struct cp210x_serial_private *priv = usb_get_serial_data(serial);
|
||||
u8 ver[3];
|
||||
int ret;
|
||||
|
||||
ret = cp210x_read_vendor_block(serial, REQTYPE_DEVICE_TO_HOST, value,
|
||||
ver, sizeof(ver));
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
dev_dbg(&serial->interface->dev, "%s - %d.%d.%d\n", __func__,
|
||||
ver[0], ver[1], ver[2]);
|
||||
|
||||
priv->fw_version = ver[0] << 16 | ver[1] << 8 | ver[2];
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void cp210x_determine_quirks(struct usb_serial *serial)
|
||||
{
|
||||
struct cp210x_serial_private *priv = usb_get_serial_data(serial);
|
||||
int ret;
|
||||
|
||||
switch (priv->partnum) {
|
||||
case CP210X_PARTNUM_CP2102N_QFN28:
|
||||
case CP210X_PARTNUM_CP2102N_QFN24:
|
||||
case CP210X_PARTNUM_CP2102N_QFN20:
|
||||
ret = cp210x_get_fw_version(serial, CP210X_GET_FW_VER_2N);
|
||||
if (ret)
|
||||
break;
|
||||
if (priv->fw_version <= 0x10004)
|
||||
priv->no_flow_control = true;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static int cp210x_attach(struct usb_serial *serial)
|
||||
{
|
||||
int result;
|
||||
|
@ -1928,6 +1999,7 @@ static int cp210x_attach(struct usb_serial *serial)
|
|||
|
||||
usb_set_serial_data(serial, priv);
|
||||
|
||||
cp210x_determine_quirks(serial);
|
||||
cp210x_init_max_speed(serial);
|
||||
|
||||
result = cp210x_gpio_init(serial);
|
||||
|
|
|
@ -611,6 +611,7 @@ static const struct usb_device_id id_table_combined[] = {
|
|||
.driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_NT_ORIONLX_PLUS_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_NT_ORION_IO_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_NT_ORIONMX_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_SYNAPSE_SS200_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_CUSTOMWARE_MINIPLEX_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_CUSTOMWARE_MINIPLEX2_PID) },
|
||||
|
|
|
@ -581,6 +581,7 @@
|
|||
#define FTDI_NT_ORIONLXM_PID 0x7c90 /* OrionLXm Substation Automation Platform */
|
||||
#define FTDI_NT_ORIONLX_PLUS_PID 0x7c91 /* OrionLX+ Substation Automation Platform */
|
||||
#define FTDI_NT_ORION_IO_PID 0x7c92 /* Orion I/O */
|
||||
#define FTDI_NT_ORIONMX_PID 0x7c93 /* OrionMX */
|
||||
|
||||
/*
|
||||
* Synapse Wireless product ids (FTDI_VID)
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* USB ZyXEL omni.net LCD PLUS driver
|
||||
* USB ZyXEL omni.net driver
|
||||
*
|
||||
* Copyright (C) 2013,2017 Johan Hovold <johan@kernel.org>
|
||||
*
|
||||
|
@ -22,10 +22,11 @@
|
|||
#include <linux/usb/serial.h>
|
||||
|
||||
#define DRIVER_AUTHOR "Alessandro Zummo"
|
||||
#define DRIVER_DESC "USB ZyXEL omni.net LCD PLUS Driver"
|
||||
#define DRIVER_DESC "USB ZyXEL omni.net Driver"
|
||||
|
||||
#define ZYXEL_VENDOR_ID 0x0586
|
||||
#define ZYXEL_OMNINET_ID 0x1000
|
||||
#define ZYXEL_OMNI_56K_PLUS_ID 0x1500
|
||||
/* This one seems to be a re-branded ZyXEL device */
|
||||
#define BT_IGNITIONPRO_ID 0x2000
|
||||
|
||||
|
@ -40,6 +41,7 @@ static void omninet_port_remove(struct usb_serial_port *port);
|
|||
|
||||
static const struct usb_device_id id_table[] = {
|
||||
{ USB_DEVICE(ZYXEL_VENDOR_ID, ZYXEL_OMNINET_ID) },
|
||||
{ USB_DEVICE(ZYXEL_VENDOR_ID, ZYXEL_OMNI_56K_PLUS_ID) },
|
||||
{ USB_DEVICE(ZYXEL_VENDOR_ID, BT_IGNITIONPRO_ID) },
|
||||
{ } /* Terminating entry */
|
||||
};
|
||||
|
@ -50,7 +52,7 @@ static struct usb_serial_driver zyxel_omninet_device = {
|
|||
.owner = THIS_MODULE,
|
||||
.name = "omninet",
|
||||
},
|
||||
.description = "ZyXEL - omni.net lcd plus usb",
|
||||
.description = "ZyXEL - omni.net usb",
|
||||
.id_table = id_table,
|
||||
.num_bulk_out = 2,
|
||||
.calc_num_ports = omninet_calc_num_ports,
|
||||
|
|
|
@ -416,7 +416,7 @@ static void qt2_close(struct usb_serial_port *port)
|
|||
|
||||
/* flush the port transmit buffer */
|
||||
i = usb_control_msg(serial->dev,
|
||||
usb_rcvctrlpipe(serial->dev, 0),
|
||||
usb_sndctrlpipe(serial->dev, 0),
|
||||
QT2_FLUSH_DEVICE, 0x40, 1,
|
||||
port_priv->device_port, NULL, 0, QT2_USB_TIMEOUT);
|
||||
|
||||
|
@ -426,7 +426,7 @@ static void qt2_close(struct usb_serial_port *port)
|
|||
|
||||
/* flush the port receive buffer */
|
||||
i = usb_control_msg(serial->dev,
|
||||
usb_rcvctrlpipe(serial->dev, 0),
|
||||
usb_sndctrlpipe(serial->dev, 0),
|
||||
QT2_FLUSH_DEVICE, 0x40, 0,
|
||||
port_priv->device_port, NULL, 0, QT2_USB_TIMEOUT);
|
||||
|
||||
|
@ -639,7 +639,7 @@ static int qt2_attach(struct usb_serial *serial)
|
|||
int status;
|
||||
|
||||
/* power on unit */
|
||||
status = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0),
|
||||
status = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
|
||||
0xc2, 0x40, 0x8000, 0, NULL, 0,
|
||||
QT2_USB_TIMEOUT);
|
||||
if (status < 0) {
|
||||
|
|
|
@ -239,7 +239,7 @@ find_mux:
|
|||
dev = class_find_device(&typec_mux_class, NULL, fwnode,
|
||||
mux_fwnode_match);
|
||||
|
||||
return dev ? to_typec_switch(dev) : ERR_PTR(-EPROBE_DEFER);
|
||||
return dev ? to_typec_mux(dev) : ERR_PTR(-EPROBE_DEFER);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -582,10 +582,15 @@ static int pmc_usb_probe_iom(struct pmc_usb *pmc)
|
|||
acpi_dev_free_resource_list(&resource_list);
|
||||
|
||||
if (!pmc->iom_base) {
|
||||
put_device(&adev->dev);
|
||||
acpi_dev_put(adev);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
if (IS_ERR(pmc->iom_base)) {
|
||||
acpi_dev_put(adev);
|
||||
return PTR_ERR(pmc->iom_base);
|
||||
}
|
||||
|
||||
pmc->iom_adev = adev;
|
||||
|
||||
return 0;
|
||||
|
@ -636,9 +641,11 @@ static int pmc_usb_probe(struct platform_device *pdev)
|
|||
break;
|
||||
|
||||
ret = pmc_usb_register_port(pmc, i, fwnode);
|
||||
if (ret)
|
||||
if (ret) {
|
||||
fwnode_handle_put(fwnode);
|
||||
goto err_remove_ports;
|
||||
}
|
||||
}
|
||||
|
||||
platform_set_drvdata(pdev, pmc);
|
||||
|
||||
|
@ -651,7 +658,7 @@ err_remove_ports:
|
|||
usb_role_switch_unregister(pmc->port[i].usb_sw);
|
||||
}
|
||||
|
||||
put_device(&pmc->iom_adev->dev);
|
||||
acpi_dev_put(pmc->iom_adev);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -667,7 +674,7 @@ static int pmc_usb_remove(struct platform_device *pdev)
|
|||
usb_role_switch_unregister(pmc->port[i].usb_sw);
|
||||
}
|
||||
|
||||
put_device(&pmc->iom_adev->dev);
|
||||
acpi_dev_put(pmc->iom_adev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -401,6 +401,8 @@ struct tcpm_port {
|
|||
unsigned int nr_src_pdo;
|
||||
u32 snk_pdo[PDO_MAX_OBJECTS];
|
||||
unsigned int nr_snk_pdo;
|
||||
u32 snk_vdo_v1[VDO_MAX_OBJECTS];
|
||||
unsigned int nr_snk_vdo_v1;
|
||||
u32 snk_vdo[VDO_MAX_OBJECTS];
|
||||
unsigned int nr_snk_vdo;
|
||||
|
||||
|
@ -1547,42 +1549,45 @@ static int tcpm_pd_svdm(struct tcpm_port *port, struct typec_altmode *adev,
|
|||
if (PD_VDO_VID(p[0]) != USB_SID_PD)
|
||||
break;
|
||||
|
||||
if (PD_VDO_SVDM_VER(p[0]) < svdm_version)
|
||||
if (PD_VDO_SVDM_VER(p[0]) < svdm_version) {
|
||||
typec_partner_set_svdm_version(port->partner,
|
||||
PD_VDO_SVDM_VER(p[0]));
|
||||
svdm_version = PD_VDO_SVDM_VER(p[0]);
|
||||
}
|
||||
|
||||
tcpm_ams_start(port, DISCOVER_IDENTITY);
|
||||
/* 6.4.4.3.1: Only respond as UFP (device) */
|
||||
if (port->data_role == TYPEC_DEVICE &&
|
||||
port->nr_snk_vdo) {
|
||||
port->ams = DISCOVER_IDENTITY;
|
||||
/*
|
||||
* Product Type DFP and Connector Type are not defined in SVDM
|
||||
* version 1.0 and shall be set to zero.
|
||||
* PD2.0 Spec 6.10.3: respond with NAK as DFP (data host)
|
||||
* PD3.1 Spec 6.4.4.2.5.1: respond with NAK if "invalid field" or
|
||||
* "wrong configuation" or "Unrecognized"
|
||||
*/
|
||||
if (typec_get_negotiated_svdm_version(typec) < SVDM_VER_2_0)
|
||||
response[1] = port->snk_vdo[0] & ~IDH_DFP_MASK
|
||||
& ~IDH_CONN_MASK;
|
||||
else
|
||||
response[1] = port->snk_vdo[0];
|
||||
for (i = 1; i < port->nr_snk_vdo; i++)
|
||||
if ((port->data_role == TYPEC_DEVICE || svdm_version >= SVDM_VER_2_0) &&
|
||||
port->nr_snk_vdo) {
|
||||
if (svdm_version < SVDM_VER_2_0) {
|
||||
for (i = 0; i < port->nr_snk_vdo_v1; i++)
|
||||
response[i + 1] = port->snk_vdo_v1[i];
|
||||
rlen = port->nr_snk_vdo_v1 + 1;
|
||||
|
||||
} else {
|
||||
for (i = 0; i < port->nr_snk_vdo; i++)
|
||||
response[i + 1] = port->snk_vdo[i];
|
||||
rlen = port->nr_snk_vdo + 1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case CMD_DISCOVER_SVID:
|
||||
tcpm_ams_start(port, DISCOVER_SVIDS);
|
||||
port->ams = DISCOVER_SVIDS;
|
||||
break;
|
||||
case CMD_DISCOVER_MODES:
|
||||
tcpm_ams_start(port, DISCOVER_MODES);
|
||||
port->ams = DISCOVER_MODES;
|
||||
break;
|
||||
case CMD_ENTER_MODE:
|
||||
tcpm_ams_start(port, DFP_TO_UFP_ENTER_MODE);
|
||||
port->ams = DFP_TO_UFP_ENTER_MODE;
|
||||
break;
|
||||
case CMD_EXIT_MODE:
|
||||
tcpm_ams_start(port, DFP_TO_UFP_EXIT_MODE);
|
||||
port->ams = DFP_TO_UFP_EXIT_MODE;
|
||||
break;
|
||||
case CMD_ATTENTION:
|
||||
tcpm_ams_start(port, ATTENTION);
|
||||
/* Attention command does not have response */
|
||||
*adev_action = ADEV_ATTENTION;
|
||||
return 0;
|
||||
|
@ -1937,6 +1942,9 @@ static void vdm_run_state_machine(struct tcpm_port *port)
|
|||
tcpm_log(port, "VDM Tx error, retry");
|
||||
port->vdm_retries++;
|
||||
port->vdm_state = VDM_STATE_READY;
|
||||
if (PD_VDO_SVDM(vdo_hdr) && PD_VDO_CMDT(vdo_hdr) == CMDT_INIT)
|
||||
tcpm_ams_finish(port);
|
||||
} else {
|
||||
tcpm_ams_finish(port);
|
||||
}
|
||||
break;
|
||||
|
@ -2183,20 +2191,25 @@ static void tcpm_handle_alert(struct tcpm_port *port, const __le32 *payload,
|
|||
|
||||
if (!type) {
|
||||
tcpm_log(port, "Alert message received with no type");
|
||||
tcpm_queue_message(port, PD_MSG_CTRL_NOT_SUPP);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Just handling non-battery alerts for now */
|
||||
if (!(type & USB_PD_ADO_TYPE_BATT_STATUS_CHANGE)) {
|
||||
switch (port->state) {
|
||||
case SRC_READY:
|
||||
case SNK_READY:
|
||||
if (port->pwr_role == TYPEC_SOURCE) {
|
||||
port->upcoming_state = GET_STATUS_SEND;
|
||||
tcpm_ams_start(port, GETTING_SOURCE_SINK_STATUS);
|
||||
} else {
|
||||
/*
|
||||
* Do not check SinkTxOk here in case the Source doesn't set its Rp to
|
||||
* SinkTxOk in time.
|
||||
*/
|
||||
port->ams = GETTING_SOURCE_SINK_STATUS;
|
||||
tcpm_set_state(port, GET_STATUS_SEND, 0);
|
||||
break;
|
||||
default:
|
||||
tcpm_queue_message(port, PD_MSG_CTRL_WAIT);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
tcpm_queue_message(port, PD_MSG_CTRL_NOT_SUPP);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2440,6 +2453,11 @@ static void tcpm_pd_data_request(struct tcpm_port *port,
|
|||
tcpm_pd_handle_state(port, BIST_RX, BIST, 0);
|
||||
break;
|
||||
case PD_DATA_ALERT:
|
||||
if (port->state != SRC_READY && port->state != SNK_READY)
|
||||
tcpm_pd_handle_state(port, port->pwr_role == TYPEC_SOURCE ?
|
||||
SRC_SOFT_RESET_WAIT_SNK_TX : SNK_SOFT_RESET,
|
||||
NONE_AMS, 0);
|
||||
else
|
||||
tcpm_handle_alert(port, msg->payload, cnt);
|
||||
break;
|
||||
case PD_DATA_BATT_STATUS:
|
||||
|
@ -2764,24 +2782,16 @@ static void tcpm_pd_ext_msg_request(struct tcpm_port *port,
|
|||
|
||||
switch (type) {
|
||||
case PD_EXT_STATUS:
|
||||
/*
|
||||
* If PPS related events raised then get PPS status to clear
|
||||
* (see USB PD 3.0 Spec, 6.5.2.4)
|
||||
*/
|
||||
if (msg->ext_msg.data[USB_PD_EXT_SDB_EVENT_FLAGS] &
|
||||
USB_PD_EXT_SDB_PPS_EVENTS)
|
||||
tcpm_pd_handle_state(port, GET_PPS_STATUS_SEND,
|
||||
GETTING_SOURCE_SINK_STATUS, 0);
|
||||
|
||||
else
|
||||
tcpm_pd_handle_state(port, ready_state(port), NONE_AMS, 0);
|
||||
break;
|
||||
case PD_EXT_PPS_STATUS:
|
||||
/*
|
||||
* For now the PPS status message is used to clear events
|
||||
* and nothing more.
|
||||
*/
|
||||
tcpm_pd_handle_state(port, ready_state(port), NONE_AMS, 0);
|
||||
if (port->ams == GETTING_SOURCE_SINK_STATUS) {
|
||||
tcpm_ams_finish(port);
|
||||
tcpm_set_state(port, ready_state(port), 0);
|
||||
} else {
|
||||
/* unexpected Status or PPS_Status Message */
|
||||
tcpm_pd_handle_state(port, port->pwr_role == TYPEC_SOURCE ?
|
||||
SRC_SOFT_RESET_WAIT_SNK_TX : SNK_SOFT_RESET,
|
||||
NONE_AMS, 0);
|
||||
}
|
||||
break;
|
||||
case PD_EXT_SOURCE_CAP_EXT:
|
||||
case PD_EXT_GET_BATT_CAP:
|
||||
|
@ -5947,6 +5957,22 @@ sink:
|
|||
return ret;
|
||||
}
|
||||
|
||||
/* If sink-vdos is found, sink-vdos-v1 is expected for backward compatibility. */
|
||||
if (port->nr_snk_vdo) {
|
||||
ret = fwnode_property_count_u32(fwnode, "sink-vdos-v1");
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
else if (ret == 0)
|
||||
return -ENODATA;
|
||||
|
||||
port->nr_snk_vdo_v1 = min(ret, VDO_MAX_OBJECTS);
|
||||
ret = fwnode_property_read_u32_array(fwnode, "sink-vdos-v1",
|
||||
port->snk_vdo_v1,
|
||||
port->nr_snk_vdo_v1);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -6312,6 +6338,11 @@ void tcpm_unregister_port(struct tcpm_port *port)
|
|||
{
|
||||
int i;
|
||||
|
||||
hrtimer_cancel(&port->send_discover_timer);
|
||||
hrtimer_cancel(&port->enable_frs_timer);
|
||||
hrtimer_cancel(&port->vdm_state_machine_timer);
|
||||
hrtimer_cancel(&port->state_machine_timer);
|
||||
|
||||
tcpm_reset_port(port);
|
||||
for (i = 0; i < ARRAY_SIZE(port->port_altmode); i++)
|
||||
typec_unregister_altmode(port->port_altmode[i]);
|
||||
|
|
|
@ -378,7 +378,7 @@ static int wcove_pd_transmit(struct tcpc_dev *tcpc,
|
|||
const u8 *data = (void *)msg;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < pd_header_cnt(msg->header) * 4 + 2; i++) {
|
||||
for (i = 0; i < pd_header_cnt_le(msg->header) * 4 + 2; i++) {
|
||||
ret = regmap_write(wcove->regmap, USBC_TX_DATA + i,
|
||||
data[i]);
|
||||
if (ret)
|
||||
|
|
|
@ -1253,6 +1253,7 @@ err_unregister:
|
|||
}
|
||||
|
||||
err_reset:
|
||||
memset(&ucsi->cap, 0, sizeof(ucsi->cap));
|
||||
ucsi_reset_ppm(ucsi);
|
||||
err:
|
||||
return ret;
|
||||
|
|
|
@ -106,6 +106,10 @@
|
|||
* <20:16> :: Reserved, Shall be set to zero
|
||||
* <15:0> :: USB-IF assigned VID for this cable vendor
|
||||
*/
|
||||
|
||||
/* PD Rev2.0 definition */
|
||||
#define IDH_PTYPE_UNDEF 0
|
||||
|
||||
/* SOP Product Type (UFP) */
|
||||
#define IDH_PTYPE_NOT_UFP 0
|
||||
#define IDH_PTYPE_HUB 1
|
||||
|
@ -163,10 +167,10 @@
|
|||
#define UFP_VDO_VER1_2 2
|
||||
|
||||
/* Device Capability */
|
||||
#define DEV_USB2_CAPABLE BIT(0)
|
||||
#define DEV_USB2_BILLBOARD BIT(1)
|
||||
#define DEV_USB3_CAPABLE BIT(2)
|
||||
#define DEV_USB4_CAPABLE BIT(3)
|
||||
#define DEV_USB2_CAPABLE (1 << 0)
|
||||
#define DEV_USB2_BILLBOARD (1 << 1)
|
||||
#define DEV_USB3_CAPABLE (1 << 2)
|
||||
#define DEV_USB4_CAPABLE (1 << 3)
|
||||
|
||||
/* Connector Type */
|
||||
#define UFP_RECEPTACLE 2
|
||||
|
@ -191,9 +195,9 @@
|
|||
|
||||
/* Alternate Modes */
|
||||
#define UFP_ALTMODE_NOT_SUPP 0
|
||||
#define UFP_ALTMODE_TBT3 BIT(0)
|
||||
#define UFP_ALTMODE_RECFG BIT(1)
|
||||
#define UFP_ALTMODE_NO_RECFG BIT(2)
|
||||
#define UFP_ALTMODE_TBT3 (1 << 0)
|
||||
#define UFP_ALTMODE_RECFG (1 << 1)
|
||||
#define UFP_ALTMODE_NO_RECFG (1 << 2)
|
||||
|
||||
/* USB Highest Speed */
|
||||
#define UFP_USB2_ONLY 0
|
||||
|
@ -217,9 +221,9 @@
|
|||
* <4:0> :: Port number
|
||||
*/
|
||||
#define DFP_VDO_VER1_1 1
|
||||
#define HOST_USB2_CAPABLE BIT(0)
|
||||
#define HOST_USB3_CAPABLE BIT(1)
|
||||
#define HOST_USB4_CAPABLE BIT(2)
|
||||
#define HOST_USB2_CAPABLE (1 << 0)
|
||||
#define HOST_USB3_CAPABLE (1 << 1)
|
||||
#define HOST_USB4_CAPABLE (1 << 2)
|
||||
#define DFP_RECEPTACLE 2
|
||||
#define DFP_CAPTIVE 3
|
||||
|
||||
|
@ -228,7 +232,25 @@
|
|||
| ((pnum) & 0x1f))
|
||||
|
||||
/*
|
||||
* Passive Cable VDO
|
||||
* Cable VDO (for both Passive and Active Cable VDO in PD Rev2.0)
|
||||
* ---------
|
||||
* <31:28> :: Cable HW version
|
||||
* <27:24> :: Cable FW version
|
||||
* <23:20> :: Reserved, Shall be set to zero
|
||||
* <19:18> :: type-C to Type-A/B/C/Captive (00b == A, 01 == B, 10 == C, 11 == Captive)
|
||||
* <17> :: Reserved, Shall be set to zero
|
||||
* <16:13> :: cable latency (0001 == <10ns(~1m length))
|
||||
* <12:11> :: cable termination type (11b == both ends active VCONN req)
|
||||
* <10> :: SSTX1 Directionality support (0b == fixed, 1b == cfgable)
|
||||
* <9> :: SSTX2 Directionality support
|
||||
* <8> :: SSRX1 Directionality support
|
||||
* <7> :: SSRX2 Directionality support
|
||||
* <6:5> :: Vbus current handling capability (01b == 3A, 10b == 5A)
|
||||
* <4> :: Vbus through cable (0b == no, 1b == yes)
|
||||
* <3> :: SOP" controller present? (0b == no, 1b == yes)
|
||||
* <2:0> :: USB SS Signaling support
|
||||
*
|
||||
* Passive Cable VDO (PD Rev3.0+)
|
||||
* ---------
|
||||
* <31:28> :: Cable HW version
|
||||
* <27:24> :: Cable FW version
|
||||
|
@ -244,7 +266,7 @@
|
|||
* <4:3> :: Reserved, Shall be set to zero
|
||||
* <2:0> :: USB highest speed
|
||||
*
|
||||
* Active Cable VDO 1
|
||||
* Active Cable VDO 1 (PD Rev3.0+)
|
||||
* ---------
|
||||
* <31:28> :: Cable HW version
|
||||
* <27:24> :: Cable FW version
|
||||
|
@ -266,7 +288,9 @@
|
|||
#define CABLE_VDO_VER1_0 0
|
||||
#define CABLE_VDO_VER1_3 3
|
||||
|
||||
/* Connector Type */
|
||||
/* Connector Type (_ATYPE and _BTYPE are for PD Rev2.0 only) */
|
||||
#define CABLE_ATYPE 0
|
||||
#define CABLE_BTYPE 1
|
||||
#define CABLE_CTYPE 2
|
||||
#define CABLE_CAPTIVE 3
|
||||
|
||||
|
@ -303,12 +327,22 @@
|
|||
#define CABLE_CURR_3A 1
|
||||
#define CABLE_CURR_5A 2
|
||||
|
||||
/* USB SuperSpeed Signaling Support (PD Rev2.0) */
|
||||
#define CABLE_USBSS_U2_ONLY 0
|
||||
#define CABLE_USBSS_U31_GEN1 1
|
||||
#define CABLE_USBSS_U31_GEN2 2
|
||||
|
||||
/* USB Highest Speed */
|
||||
#define CABLE_USB2_ONLY 0
|
||||
#define CABLE_USB32_GEN1 1
|
||||
#define CABLE_USB32_4_GEN2 2
|
||||
#define CABLE_USB4_GEN3 3
|
||||
|
||||
#define VDO_CABLE(hw, fw, cbl, lat, term, tx1d, tx2d, rx1d, rx2d, cur, vps, sopp, usbss) \
|
||||
(((hw) & 0x7) << 28 | ((fw) & 0x7) << 24 | ((cbl) & 0x3) << 18 \
|
||||
| ((lat) & 0x7) << 13 | ((term) & 0x3) << 11 | (tx1d) << 10 \
|
||||
| (tx2d) << 9 | (rx1d) << 8 | (rx2d) << 7 | ((cur) & 0x3) << 5 \
|
||||
| (vps) << 4 | (sopp) << 3 | ((usbss) & 0x7))
|
||||
#define VDO_PCABLE(hw, fw, ver, conn, lat, term, vbm, cur, spd) \
|
||||
(((hw) & 0xf) << 28 | ((fw) & 0xf) << 24 | ((ver) & 0x7) << 21 \
|
||||
| ((conn) & 0x3) << 18 | ((lat) & 0xf) << 13 | ((term) & 0x3) << 11 \
|
||||
|
@ -373,6 +407,35 @@
|
|||
| ((hops) & 0x3) << 6 | (u2) << 5 | (u32) << 4 | (lane) << 3 \
|
||||
| (iso) << 2 | (gen))
|
||||
|
||||
/*
|
||||
* AMA VDO (PD Rev2.0)
|
||||
* ---------
|
||||
* <31:28> :: Cable HW version
|
||||
* <27:24> :: Cable FW version
|
||||
* <23:12> :: Reserved, Shall be set to zero
|
||||
* <11> :: SSTX1 Directionality support (0b == fixed, 1b == cfgable)
|
||||
* <10> :: SSTX2 Directionality support
|
||||
* <9> :: SSRX1 Directionality support
|
||||
* <8> :: SSRX2 Directionality support
|
||||
* <7:5> :: Vconn power
|
||||
* <4> :: Vconn power required
|
||||
* <3> :: Vbus power required
|
||||
* <2:0> :: USB SS Signaling support
|
||||
*/
|
||||
#define VDO_AMA(hw, fw, tx1d, tx2d, rx1d, rx2d, vcpwr, vcr, vbr, usbss) \
|
||||
(((hw) & 0x7) << 28 | ((fw) & 0x7) << 24 \
|
||||
| (tx1d) << 11 | (tx2d) << 10 | (rx1d) << 9 | (rx2d) << 8 \
|
||||
| ((vcpwr) & 0x7) << 5 | (vcr) << 4 | (vbr) << 3 \
|
||||
| ((usbss) & 0x7))
|
||||
|
||||
#define PD_VDO_AMA_VCONN_REQ(vdo) (((vdo) >> 4) & 1)
|
||||
#define PD_VDO_AMA_VBUS_REQ(vdo) (((vdo) >> 3) & 1)
|
||||
|
||||
#define AMA_USBSS_U2_ONLY 0
|
||||
#define AMA_USBSS_U31_GEN1 1
|
||||
#define AMA_USBSS_U31_GEN2 2
|
||||
#define AMA_USBSS_BBONLY 3
|
||||
|
||||
/*
|
||||
* VPD VDO
|
||||
* ---------
|
||||
|
|
|
@ -460,7 +460,7 @@ static inline unsigned int rdo_max_power(u32 rdo)
|
|||
#define PD_T_RECEIVER_RESPONSE 15 /* 15ms max */
|
||||
#define PD_T_SOURCE_ACTIVITY 45
|
||||
#define PD_T_SINK_ACTIVITY 135
|
||||
#define PD_T_SINK_WAIT_CAP 240
|
||||
#define PD_T_SINK_WAIT_CAP 310 /* 310 - 620 ms */
|
||||
#define PD_T_PS_TRANSITION 500
|
||||
#define PD_T_SRC_TRANSITION 35
|
||||
#define PD_T_DRP_SNK 40
|
||||
|
|
|
@ -24,8 +24,4 @@ enum usb_pd_ext_sdb_fields {
|
|||
#define USB_PD_EXT_SDB_EVENT_OVP BIT(3)
|
||||
#define USB_PD_EXT_SDB_EVENT_CF_CV_MODE BIT(4)
|
||||
|
||||
#define USB_PD_EXT_SDB_PPS_EVENTS (USB_PD_EXT_SDB_EVENT_OCP | \
|
||||
USB_PD_EXT_SDB_EVENT_OTP | \
|
||||
USB_PD_EXT_SDB_EVENT_OVP)
|
||||
|
||||
#endif /* __LINUX_USB_PD_EXT_SDB_H */
|
||||
|
|
Loading…
Reference in New Issue