mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-09-29 05:44:11 +00:00
USB/Thunderbolt driver fixes for 6.0-rc4
Here are a lot of small USB and Thunderbolt driver fixes for 6.0-rc4 for reported problems. Included in here are: - new usb-serial driver ids - dwc3 driver bugfixes for reported problems with 6.0-rc1 - new device quirks, and reverts of some quirks that were incorrect - gadget driver bugfixes for reported problems - USB host controller bugfixes (xhci and others) - other small USB fixes, details in the shortlog - small thunderbolt driver fixes All of these have been in linux-next with no reported issues. Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> -----BEGIN PGP SIGNATURE----- iG0EABECAC0WIQT0tgzFv3jCIUoxPcsxR9QN2y37KQUCYxIfKA8cZ3JlZ0Brcm9h aC5jb20ACgkQMUfUDdst+yk7iQCeN8Lg6Sm+2bdO7sh38QDEKCIfOKEAoM+yHA3f 2kDkCyueaTn7ra388hSy =iJh8 -----END PGP SIGNATURE----- Merge tag 'usb-6.0-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb Pull USB/Thunderbolt driver fixes from Greg KH: "Here are a lot of small USB and Thunderbolt driver fixes for 6.0-rc4 for reported problems. Included in here are: - new usb-serial driver ids - dwc3 driver bugfixes for reported problems with 6.0-rc1 - new device quirks, and reverts of some quirks that were incorrect - gadget driver bugfixes for reported problems - USB host controller bugfixes (xhci and others) - other small USB fixes, details in the shortlog - small thunderbolt driver fixes All of these have been in linux-next with no reported issues" * tag 'usb-6.0-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb: (51 commits) Revert "usb: gadget: udc-xilinx: replace memcpy with memcpy_toio" usb: storage: Add ASUS <0x0b05:0x1932> to IGNORE_UAS USB: serial: ch341: fix disabled rx timer on older devices USB: serial: ch341: fix lost character on LCR updates USB: serial: cp210x: add Decagon UCA device id Revert "usb: add quirks for Lenovo OneLink+ Dock" usb: cdns3: fix issue with rearming ISO OUT endpoint usb: cdns3: fix incorrect handling TRB_SMM flag for ISOC transfer usb: gadget: mass_storage: Fix cdrom data transfers on MAC-OS media: mceusb: Use new usb_control_msg_*() routines USB: core: Prevent nested device-reset calls USB: gadget: Fix obscure lockdep violation for udc_mutex usb: dwc2: fix wrong order of phy_power_on and phy_init usb: gadget: udc-xilinx: replace memcpy with memcpy_toio usb: typec: Remove retimers properly usb: dwc3: disable USB core PHY management usb: add quirks for Lenovo OneLink+ Dock USB: serial: option: add support for Cinterion MV32-WA/WB RmNet mode USB: serial: ftdi_sio: add Omron CS1W-CIF31 device id USB: serial: option: add Quectel EM060K modem ...
This commit is contained in:
commit
fd59585c42
38 changed files with 303 additions and 167 deletions
|
@ -24,6 +24,7 @@ properties:
|
|||
- mediatek,mt2712-mtu3
|
||||
- mediatek,mt8173-mtu3
|
||||
- mediatek,mt8183-mtu3
|
||||
- mediatek,mt8188-mtu3
|
||||
- mediatek,mt8192-mtu3
|
||||
- mediatek,mt8195-mtu3
|
||||
- const: mediatek,mtu3
|
||||
|
|
|
@ -33,6 +33,7 @@ properties:
|
|||
- qcom,sm6115-dwc3
|
||||
- qcom,sm6125-dwc3
|
||||
- qcom,sm6350-dwc3
|
||||
- qcom,sm6375-dwc3
|
||||
- qcom,sm8150-dwc3
|
||||
- qcom,sm8250-dwc3
|
||||
- qcom,sm8350-dwc3
|
||||
|
@ -108,12 +109,17 @@ properties:
|
|||
HS/FS/LS modes are supported.
|
||||
type: boolean
|
||||
|
||||
wakeup-source: true
|
||||
|
||||
# Required child node:
|
||||
|
||||
patternProperties:
|
||||
"^usb@[0-9a-f]+$":
|
||||
$ref: snps,dwc3.yaml#
|
||||
|
||||
properties:
|
||||
wakeup-source: false
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
|
|
|
@ -1416,42 +1416,37 @@ static void mceusb_gen1_init(struct mceusb_dev *ir)
|
|||
{
|
||||
int ret;
|
||||
struct device *dev = ir->dev;
|
||||
char *data;
|
||||
|
||||
data = kzalloc(USB_CTRL_MSG_SZ, GFP_KERNEL);
|
||||
if (!data) {
|
||||
dev_err(dev, "%s: memory allocation failed!", __func__);
|
||||
return;
|
||||
}
|
||||
char data[USB_CTRL_MSG_SZ];
|
||||
|
||||
/*
|
||||
* This is a strange one. Windows issues a set address to the device
|
||||
* on the receive control pipe and expect a certain value pair back
|
||||
*/
|
||||
ret = usb_control_msg(ir->usbdev, usb_rcvctrlpipe(ir->usbdev, 0),
|
||||
USB_REQ_SET_ADDRESS, USB_TYPE_VENDOR, 0, 0,
|
||||
data, USB_CTRL_MSG_SZ, 3000);
|
||||
ret = usb_control_msg_recv(ir->usbdev, 0, USB_REQ_SET_ADDRESS,
|
||||
USB_DIR_IN | USB_TYPE_VENDOR,
|
||||
0, 0, data, USB_CTRL_MSG_SZ, 3000,
|
||||
GFP_KERNEL);
|
||||
dev_dbg(dev, "set address - ret = %d", ret);
|
||||
dev_dbg(dev, "set address - data[0] = %d, data[1] = %d",
|
||||
data[0], data[1]);
|
||||
|
||||
/* set feature: bit rate 38400 bps */
|
||||
ret = usb_control_msg(ir->usbdev, usb_sndctrlpipe(ir->usbdev, 0),
|
||||
USB_REQ_SET_FEATURE, USB_TYPE_VENDOR,
|
||||
0xc04e, 0x0000, NULL, 0, 3000);
|
||||
ret = usb_control_msg_send(ir->usbdev, 0,
|
||||
USB_REQ_SET_FEATURE, USB_TYPE_VENDOR,
|
||||
0xc04e, 0x0000, NULL, 0, 3000, GFP_KERNEL);
|
||||
|
||||
dev_dbg(dev, "set feature - ret = %d", ret);
|
||||
|
||||
/* bRequest 4: set char length to 8 bits */
|
||||
ret = usb_control_msg(ir->usbdev, usb_sndctrlpipe(ir->usbdev, 0),
|
||||
4, USB_TYPE_VENDOR,
|
||||
0x0808, 0x0000, NULL, 0, 3000);
|
||||
ret = usb_control_msg_send(ir->usbdev, 0,
|
||||
4, USB_TYPE_VENDOR,
|
||||
0x0808, 0x0000, NULL, 0, 3000, GFP_KERNEL);
|
||||
dev_dbg(dev, "set char length - retB = %d", ret);
|
||||
|
||||
/* bRequest 2: set handshaking to use DTR/DSR */
|
||||
ret = usb_control_msg(ir->usbdev, usb_sndctrlpipe(ir->usbdev, 0),
|
||||
2, USB_TYPE_VENDOR,
|
||||
0x0000, 0x0100, NULL, 0, 3000);
|
||||
ret = usb_control_msg_send(ir->usbdev, 0,
|
||||
2, USB_TYPE_VENDOR,
|
||||
0x0000, 0x0100, NULL, 0, 3000, GFP_KERNEL);
|
||||
dev_dbg(dev, "set handshake - retC = %d", ret);
|
||||
|
||||
/* device resume */
|
||||
|
@ -1459,8 +1454,6 @@ static void mceusb_gen1_init(struct mceusb_dev *ir)
|
|||
|
||||
/* get hw/sw revision? */
|
||||
mce_command_out(ir, GET_REVISION, sizeof(GET_REVISION));
|
||||
|
||||
kfree(data);
|
||||
}
|
||||
|
||||
static void mceusb_gen2_init(struct mceusb_dev *ir)
|
||||
|
|
|
@ -407,7 +407,7 @@ static void tb_ctl_rx_submit(struct ctl_pkg *pkg)
|
|||
|
||||
static int tb_async_error(const struct ctl_pkg *pkg)
|
||||
{
|
||||
const struct cfg_error_pkg *error = (const struct cfg_error_pkg *)pkg;
|
||||
const struct cfg_error_pkg *error = pkg->buffer;
|
||||
|
||||
if (pkg->frame.eof != TB_CFG_PKG_ERROR)
|
||||
return false;
|
||||
|
|
|
@ -3786,14 +3786,18 @@ int tb_switch_pcie_l1_enable(struct tb_switch *sw)
|
|||
*/
|
||||
int tb_switch_xhci_connect(struct tb_switch *sw)
|
||||
{
|
||||
bool usb_port1, usb_port3, xhci_port1, xhci_port3;
|
||||
struct tb_port *port1, *port3;
|
||||
int ret;
|
||||
|
||||
if (sw->generation != 3)
|
||||
return 0;
|
||||
|
||||
port1 = &sw->ports[1];
|
||||
port3 = &sw->ports[3];
|
||||
|
||||
if (tb_switch_is_alpine_ridge(sw)) {
|
||||
bool usb_port1, usb_port3, xhci_port1, xhci_port3;
|
||||
|
||||
usb_port1 = tb_lc_is_usb_plugged(port1);
|
||||
usb_port3 = tb_lc_is_usb_plugged(port3);
|
||||
xhci_port1 = tb_lc_is_xhci_connected(port1);
|
||||
|
|
|
@ -1530,7 +1530,8 @@ static void cdns3_transfer_completed(struct cdns3_device *priv_dev,
|
|||
TRB_LEN(le32_to_cpu(trb->length));
|
||||
|
||||
if (priv_req->num_of_trb > 1 &&
|
||||
le32_to_cpu(trb->control) & TRB_SMM)
|
||||
le32_to_cpu(trb->control) & TRB_SMM &&
|
||||
le32_to_cpu(trb->control) & TRB_CHAIN)
|
||||
transfer_end = true;
|
||||
|
||||
cdns3_ep_inc_deq(priv_ep);
|
||||
|
@ -1690,6 +1691,7 @@ static int cdns3_check_ep_interrupt_proceed(struct cdns3_endpoint *priv_ep)
|
|||
ep_cfg &= ~EP_CFG_ENABLE;
|
||||
writel(ep_cfg, &priv_dev->regs->ep_cfg);
|
||||
priv_ep->flags &= ~EP_QUIRK_ISO_OUT_EN;
|
||||
priv_ep->flags |= EP_UPDATE_EP_TRBADDR;
|
||||
}
|
||||
cdns3_transfer_completed(priv_dev, priv_ep);
|
||||
} else if (!(priv_ep->flags & EP_STALLED) &&
|
||||
|
|
|
@ -1810,6 +1810,9 @@ static const struct usb_device_id acm_ids[] = {
|
|||
{ USB_DEVICE(0x09d8, 0x0320), /* Elatec GmbH TWN3 */
|
||||
.driver_info = NO_UNION_NORMAL, /* has misplaced union descriptor */
|
||||
},
|
||||
{ USB_DEVICE(0x0c26, 0x0020), /* Icom ICF3400 Serie */
|
||||
.driver_info = NO_UNION_NORMAL, /* reports zero length descriptor */
|
||||
},
|
||||
{ USB_DEVICE(0x0ca6, 0xa050), /* Castles VEGA3000 */
|
||||
.driver_info = NO_UNION_NORMAL, /* reports zero length descriptor */
|
||||
},
|
||||
|
|
|
@ -6038,6 +6038,11 @@ static int usb_reset_and_verify_device(struct usb_device *udev)
|
|||
* the reset is over (using their post_reset method).
|
||||
*
|
||||
* Return: The same as for usb_reset_and_verify_device().
|
||||
* However, if a reset is already in progress (for instance, if a
|
||||
* driver doesn't have pre_ or post_reset() callbacks, and while
|
||||
* being unbound or re-bound during the ongoing reset its disconnect()
|
||||
* or probe() routine tries to perform a second, nested reset), the
|
||||
* routine returns -EINPROGRESS.
|
||||
*
|
||||
* Note:
|
||||
* The caller must own the device lock. For example, it's safe to use
|
||||
|
@ -6071,6 +6076,10 @@ int usb_reset_device(struct usb_device *udev)
|
|||
return -EISDIR;
|
||||
}
|
||||
|
||||
if (udev->reset_in_progress)
|
||||
return -EINPROGRESS;
|
||||
udev->reset_in_progress = 1;
|
||||
|
||||
port_dev = hub->ports[udev->portnum - 1];
|
||||
|
||||
/*
|
||||
|
@ -6135,6 +6144,7 @@ int usb_reset_device(struct usb_device *udev)
|
|||
|
||||
usb_autosuspend_device(udev);
|
||||
memalloc_noio_restore(noio_flag);
|
||||
udev->reset_in_progress = 0;
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(usb_reset_device);
|
||||
|
|
|
@ -154,9 +154,9 @@ static int __dwc2_lowlevel_hw_enable(struct dwc2_hsotg *hsotg)
|
|||
} else if (hsotg->plat && hsotg->plat->phy_init) {
|
||||
ret = hsotg->plat->phy_init(pdev, hsotg->plat->phy_type);
|
||||
} else {
|
||||
ret = phy_power_on(hsotg->phy);
|
||||
ret = phy_init(hsotg->phy);
|
||||
if (ret == 0)
|
||||
ret = phy_init(hsotg->phy);
|
||||
ret = phy_power_on(hsotg->phy);
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
@ -188,9 +188,9 @@ static int __dwc2_lowlevel_hw_disable(struct dwc2_hsotg *hsotg)
|
|||
} else if (hsotg->plat && hsotg->plat->phy_exit) {
|
||||
ret = hsotg->plat->phy_exit(pdev, hsotg->plat->phy_type);
|
||||
} else {
|
||||
ret = phy_exit(hsotg->phy);
|
||||
ret = phy_power_off(hsotg->phy);
|
||||
if (ret == 0)
|
||||
ret = phy_power_off(hsotg->phy);
|
||||
ret = phy_exit(hsotg->phy);
|
||||
}
|
||||
if (ret)
|
||||
return ret;
|
||||
|
|
|
@ -833,15 +833,16 @@ static void dwc3_core_exit(struct dwc3 *dwc)
|
|||
{
|
||||
dwc3_event_buffers_cleanup(dwc);
|
||||
|
||||
usb_phy_set_suspend(dwc->usb2_phy, 1);
|
||||
usb_phy_set_suspend(dwc->usb3_phy, 1);
|
||||
phy_power_off(dwc->usb2_generic_phy);
|
||||
phy_power_off(dwc->usb3_generic_phy);
|
||||
|
||||
usb_phy_shutdown(dwc->usb2_phy);
|
||||
usb_phy_shutdown(dwc->usb3_phy);
|
||||
phy_exit(dwc->usb2_generic_phy);
|
||||
phy_exit(dwc->usb3_generic_phy);
|
||||
|
||||
usb_phy_set_suspend(dwc->usb2_phy, 1);
|
||||
usb_phy_set_suspend(dwc->usb3_phy, 1);
|
||||
phy_power_off(dwc->usb2_generic_phy);
|
||||
phy_power_off(dwc->usb3_generic_phy);
|
||||
dwc3_clk_disable(dwc);
|
||||
reset_control_assert(dwc->reset);
|
||||
}
|
||||
|
@ -1821,7 +1822,6 @@ static int dwc3_probe(struct platform_device *pdev)
|
|||
|
||||
platform_set_drvdata(pdev, dwc);
|
||||
dwc3_cache_hwparams(dwc);
|
||||
device_init_wakeup(&pdev->dev, of_property_read_bool(dev->of_node, "wakeup-source"));
|
||||
|
||||
spin_lock_init(&dwc->lock);
|
||||
mutex_init(&dwc->mutex);
|
||||
|
@ -1879,16 +1879,16 @@ static int dwc3_probe(struct platform_device *pdev)
|
|||
dwc3_debugfs_exit(dwc);
|
||||
dwc3_event_buffers_cleanup(dwc);
|
||||
|
||||
usb_phy_shutdown(dwc->usb2_phy);
|
||||
usb_phy_shutdown(dwc->usb3_phy);
|
||||
phy_exit(dwc->usb2_generic_phy);
|
||||
phy_exit(dwc->usb3_generic_phy);
|
||||
|
||||
usb_phy_set_suspend(dwc->usb2_phy, 1);
|
||||
usb_phy_set_suspend(dwc->usb3_phy, 1);
|
||||
phy_power_off(dwc->usb2_generic_phy);
|
||||
phy_power_off(dwc->usb3_generic_phy);
|
||||
|
||||
usb_phy_shutdown(dwc->usb2_phy);
|
||||
usb_phy_shutdown(dwc->usb3_phy);
|
||||
phy_exit(dwc->usb2_generic_phy);
|
||||
phy_exit(dwc->usb3_generic_phy);
|
||||
|
||||
dwc3_ulpi_exit(dwc);
|
||||
|
||||
err4:
|
||||
|
@ -1983,7 +1983,7 @@ static int dwc3_suspend_common(struct dwc3 *dwc, pm_message_t msg)
|
|||
dwc3_core_exit(dwc);
|
||||
break;
|
||||
case DWC3_GCTL_PRTCAP_HOST:
|
||||
if (!PMSG_IS_AUTO(msg) && !device_can_wakeup(dwc->dev)) {
|
||||
if (!PMSG_IS_AUTO(msg) && !device_may_wakeup(dwc->dev)) {
|
||||
dwc3_core_exit(dwc);
|
||||
break;
|
||||
}
|
||||
|
@ -2044,7 +2044,7 @@ static int dwc3_resume_common(struct dwc3 *dwc, pm_message_t msg)
|
|||
spin_unlock_irqrestore(&dwc->lock, flags);
|
||||
break;
|
||||
case DWC3_GCTL_PRTCAP_HOST:
|
||||
if (!PMSG_IS_AUTO(msg) && !device_can_wakeup(dwc->dev)) {
|
||||
if (!PMSG_IS_AUTO(msg) && !device_may_wakeup(dwc->dev)) {
|
||||
ret = dwc3_core_init_for_resume(dwc);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
|
|
@ -44,6 +44,7 @@
|
|||
#define PCI_DEVICE_ID_INTEL_ADLP 0x51ee
|
||||
#define PCI_DEVICE_ID_INTEL_ADLM 0x54ee
|
||||
#define PCI_DEVICE_ID_INTEL_ADLS 0x7ae1
|
||||
#define PCI_DEVICE_ID_INTEL_RPL 0x460e
|
||||
#define PCI_DEVICE_ID_INTEL_RPLS 0x7a61
|
||||
#define PCI_DEVICE_ID_INTEL_MTLP 0x7ec1
|
||||
#define PCI_DEVICE_ID_INTEL_MTL 0x7e7e
|
||||
|
@ -456,6 +457,9 @@ static const struct pci_device_id dwc3_pci_id_table[] = {
|
|||
{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_ADLS),
|
||||
(kernel_ulong_t) &dwc3_pci_intel_swnode, },
|
||||
|
||||
{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_RPL),
|
||||
(kernel_ulong_t) &dwc3_pci_intel_swnode, },
|
||||
|
||||
{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_RPLS),
|
||||
(kernel_ulong_t) &dwc3_pci_intel_swnode, },
|
||||
|
||||
|
|
|
@ -17,7 +17,6 @@
|
|||
#include <linux/of_platform.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/phy/phy.h>
|
||||
#include <linux/pm_domain.h>
|
||||
#include <linux/usb/of.h>
|
||||
#include <linux/reset.h>
|
||||
#include <linux/iopoll.h>
|
||||
|
@ -299,11 +298,24 @@ static void dwc3_qcom_interconnect_exit(struct dwc3_qcom *qcom)
|
|||
icc_put(qcom->icc_path_apps);
|
||||
}
|
||||
|
||||
/* Only usable in contexts where the role can not change. */
|
||||
static bool dwc3_qcom_is_host(struct dwc3_qcom *qcom)
|
||||
{
|
||||
struct dwc3 *dwc = platform_get_drvdata(qcom->dwc3);
|
||||
|
||||
return dwc->xhci;
|
||||
}
|
||||
|
||||
static enum usb_device_speed dwc3_qcom_read_usb2_speed(struct dwc3_qcom *qcom)
|
||||
{
|
||||
struct dwc3 *dwc = platform_get_drvdata(qcom->dwc3);
|
||||
struct usb_hcd *hcd = platform_get_drvdata(dwc->xhci);
|
||||
struct usb_device *udev;
|
||||
struct usb_hcd __maybe_unused *hcd;
|
||||
|
||||
/*
|
||||
* FIXME: Fix this layering violation.
|
||||
*/
|
||||
hcd = platform_get_drvdata(dwc->xhci);
|
||||
|
||||
/*
|
||||
* It is possible to query the speed of all children of
|
||||
|
@ -311,8 +323,11 @@ static enum usb_device_speed dwc3_qcom_read_usb2_speed(struct dwc3_qcom *qcom)
|
|||
* currently supports only 1 port per controller. So
|
||||
* this is sufficient.
|
||||
*/
|
||||
#ifdef CONFIG_USB
|
||||
udev = usb_hub_find_child(hcd->self.root_hub, 1);
|
||||
|
||||
#else
|
||||
udev = NULL;
|
||||
#endif
|
||||
if (!udev)
|
||||
return USB_SPEED_UNKNOWN;
|
||||
|
||||
|
@ -387,7 +402,7 @@ static void dwc3_qcom_enable_interrupts(struct dwc3_qcom *qcom)
|
|||
dwc3_qcom_enable_wakeup_irq(qcom->ss_phy_irq, 0);
|
||||
}
|
||||
|
||||
static int dwc3_qcom_suspend(struct dwc3_qcom *qcom)
|
||||
static int dwc3_qcom_suspend(struct dwc3_qcom *qcom, bool wakeup)
|
||||
{
|
||||
u32 val;
|
||||
int i, ret;
|
||||
|
@ -406,7 +421,11 @@ static int dwc3_qcom_suspend(struct dwc3_qcom *qcom)
|
|||
if (ret)
|
||||
dev_warn(qcom->dev, "failed to disable interconnect: %d\n", ret);
|
||||
|
||||
if (device_may_wakeup(qcom->dev)) {
|
||||
/*
|
||||
* The role is stable during suspend as role switching is done from a
|
||||
* freezable workqueue.
|
||||
*/
|
||||
if (dwc3_qcom_is_host(qcom) && wakeup) {
|
||||
qcom->usb2_speed = dwc3_qcom_read_usb2_speed(qcom);
|
||||
dwc3_qcom_enable_interrupts(qcom);
|
||||
}
|
||||
|
@ -416,7 +435,7 @@ static int dwc3_qcom_suspend(struct dwc3_qcom *qcom)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int dwc3_qcom_resume(struct dwc3_qcom *qcom)
|
||||
static int dwc3_qcom_resume(struct dwc3_qcom *qcom, bool wakeup)
|
||||
{
|
||||
int ret;
|
||||
int i;
|
||||
|
@ -424,7 +443,7 @@ static int dwc3_qcom_resume(struct dwc3_qcom *qcom)
|
|||
if (!qcom->is_suspended)
|
||||
return 0;
|
||||
|
||||
if (device_may_wakeup(qcom->dev))
|
||||
if (dwc3_qcom_is_host(qcom) && wakeup)
|
||||
dwc3_qcom_disable_interrupts(qcom);
|
||||
|
||||
for (i = 0; i < qcom->num_clocks; i++) {
|
||||
|
@ -458,7 +477,11 @@ static irqreturn_t qcom_dwc3_resume_irq(int irq, void *data)
|
|||
if (qcom->pm_suspended)
|
||||
return IRQ_HANDLED;
|
||||
|
||||
if (dwc->xhci)
|
||||
/*
|
||||
* This is safe as role switching is done from a freezable workqueue
|
||||
* and the wakeup interrupts are disabled as part of resume.
|
||||
*/
|
||||
if (dwc3_qcom_is_host(qcom))
|
||||
pm_runtime_resume(&dwc->xhci->dev);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
|
@ -757,13 +780,13 @@ dwc3_qcom_create_urs_usb_platdev(struct device *dev)
|
|||
|
||||
static int dwc3_qcom_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device_node *np = pdev->dev.of_node;
|
||||
struct device *dev = &pdev->dev;
|
||||
struct dwc3_qcom *qcom;
|
||||
struct resource *res, *parent_res = NULL;
|
||||
int ret, i;
|
||||
bool ignore_pipe_clk;
|
||||
struct generic_pm_domain *genpd;
|
||||
struct device_node *np = pdev->dev.of_node;
|
||||
struct device *dev = &pdev->dev;
|
||||
struct dwc3_qcom *qcom;
|
||||
struct resource *res, *parent_res = NULL;
|
||||
int ret, i;
|
||||
bool ignore_pipe_clk;
|
||||
bool wakeup_source;
|
||||
|
||||
qcom = devm_kzalloc(&pdev->dev, sizeof(*qcom), GFP_KERNEL);
|
||||
if (!qcom)
|
||||
|
@ -772,8 +795,6 @@ static int dwc3_qcom_probe(struct platform_device *pdev)
|
|||
platform_set_drvdata(pdev, qcom);
|
||||
qcom->dev = &pdev->dev;
|
||||
|
||||
genpd = pd_to_genpd(qcom->dev->pm_domain);
|
||||
|
||||
if (has_acpi_companion(dev)) {
|
||||
qcom->acpi_pdata = acpi_device_get_match_data(dev);
|
||||
if (!qcom->acpi_pdata) {
|
||||
|
@ -881,16 +902,9 @@ static int dwc3_qcom_probe(struct platform_device *pdev)
|
|||
if (ret)
|
||||
goto interconnect_exit;
|
||||
|
||||
if (device_can_wakeup(&qcom->dwc3->dev)) {
|
||||
/*
|
||||
* Setting GENPD_FLAG_ALWAYS_ON flag takes care of keeping
|
||||
* genpd on in both runtime suspend and system suspend cases.
|
||||
*/
|
||||
genpd->flags |= GENPD_FLAG_ALWAYS_ON;
|
||||
device_init_wakeup(&pdev->dev, true);
|
||||
} else {
|
||||
genpd->flags |= GENPD_FLAG_RPM_ALWAYS_ON;
|
||||
}
|
||||
wakeup_source = of_property_read_bool(dev->of_node, "wakeup-source");
|
||||
device_init_wakeup(&pdev->dev, wakeup_source);
|
||||
device_init_wakeup(&qcom->dwc3->dev, wakeup_source);
|
||||
|
||||
qcom->is_suspended = false;
|
||||
pm_runtime_set_active(dev);
|
||||
|
@ -944,39 +958,45 @@ static int dwc3_qcom_remove(struct platform_device *pdev)
|
|||
static int __maybe_unused dwc3_qcom_pm_suspend(struct device *dev)
|
||||
{
|
||||
struct dwc3_qcom *qcom = dev_get_drvdata(dev);
|
||||
int ret = 0;
|
||||
bool wakeup = device_may_wakeup(dev);
|
||||
int ret;
|
||||
|
||||
ret = dwc3_qcom_suspend(qcom);
|
||||
if (!ret)
|
||||
qcom->pm_suspended = true;
|
||||
ret = dwc3_qcom_suspend(qcom, wakeup);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return ret;
|
||||
qcom->pm_suspended = true;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __maybe_unused dwc3_qcom_pm_resume(struct device *dev)
|
||||
{
|
||||
struct dwc3_qcom *qcom = dev_get_drvdata(dev);
|
||||
bool wakeup = device_may_wakeup(dev);
|
||||
int ret;
|
||||
|
||||
ret = dwc3_qcom_resume(qcom);
|
||||
if (!ret)
|
||||
qcom->pm_suspended = false;
|
||||
ret = dwc3_qcom_resume(qcom, wakeup);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return ret;
|
||||
qcom->pm_suspended = false;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __maybe_unused dwc3_qcom_runtime_suspend(struct device *dev)
|
||||
{
|
||||
struct dwc3_qcom *qcom = dev_get_drvdata(dev);
|
||||
|
||||
return dwc3_qcom_suspend(qcom);
|
||||
return dwc3_qcom_suspend(qcom, true);
|
||||
}
|
||||
|
||||
static int __maybe_unused dwc3_qcom_runtime_resume(struct device *dev)
|
||||
{
|
||||
struct dwc3_qcom *qcom = dev_get_drvdata(dev);
|
||||
|
||||
return dwc3_qcom_resume(qcom);
|
||||
return dwc3_qcom_resume(qcom, true);
|
||||
}
|
||||
|
||||
static const struct dev_pm_ops dwc3_qcom_dev_pm_ops = {
|
||||
|
|
|
@ -2539,9 +2539,6 @@ static int dwc3_gadget_pullup(struct usb_gadget *g, int is_on)
|
|||
|
||||
is_on = !!is_on;
|
||||
|
||||
if (dwc->pullups_connected == is_on)
|
||||
return 0;
|
||||
|
||||
dwc->softconnect = is_on;
|
||||
|
||||
/*
|
||||
|
@ -2566,6 +2563,11 @@ static int dwc3_gadget_pullup(struct usb_gadget *g, int is_on)
|
|||
return 0;
|
||||
}
|
||||
|
||||
if (dwc->pullups_connected == is_on) {
|
||||
pm_runtime_put(dwc->dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!is_on) {
|
||||
ret = dwc3_gadget_soft_disconnect(dwc);
|
||||
} else {
|
||||
|
|
|
@ -11,8 +11,13 @@
|
|||
#include <linux/of.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
#include "../host/xhci-plat.h"
|
||||
#include "core.h"
|
||||
|
||||
static const struct xhci_plat_priv dwc3_xhci_plat_priv = {
|
||||
.quirks = XHCI_SKIP_PHY_INIT,
|
||||
};
|
||||
|
||||
static void dwc3_host_fill_xhci_irq_res(struct dwc3 *dwc,
|
||||
int irq, char *name)
|
||||
{
|
||||
|
@ -92,6 +97,11 @@ int dwc3_host_init(struct dwc3 *dwc)
|
|||
goto err;
|
||||
}
|
||||
|
||||
ret = platform_device_add_data(xhci, &dwc3_xhci_plat_priv,
|
||||
sizeof(dwc3_xhci_plat_priv));
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
memset(props, 0, sizeof(struct property_entry) * ARRAY_SIZE(props));
|
||||
|
||||
if (dwc->usb3_lpm_capable)
|
||||
|
@ -135,4 +145,5 @@ int dwc3_host_init(struct dwc3 *dwc)
|
|||
void dwc3_host_exit(struct dwc3 *dwc)
|
||||
{
|
||||
platform_device_unregister(dwc->xhci);
|
||||
dwc->xhci = NULL;
|
||||
}
|
||||
|
|
|
@ -291,6 +291,12 @@ static struct usb_endpoint_descriptor ss_ep_int_desc = {
|
|||
.bInterval = 4,
|
||||
};
|
||||
|
||||
static struct usb_ss_ep_comp_descriptor ss_ep_int_desc_comp = {
|
||||
.bLength = sizeof(ss_ep_int_desc_comp),
|
||||
.bDescriptorType = USB_DT_SS_ENDPOINT_COMP,
|
||||
.wBytesPerInterval = cpu_to_le16(6),
|
||||
};
|
||||
|
||||
/* Audio Streaming OUT Interface - Alt0 */
|
||||
static struct usb_interface_descriptor std_as_out_if0_desc = {
|
||||
.bLength = sizeof std_as_out_if0_desc,
|
||||
|
@ -604,7 +610,8 @@ static struct usb_descriptor_header *ss_audio_desc[] = {
|
|||
(struct usb_descriptor_header *)&in_feature_unit_desc,
|
||||
(struct usb_descriptor_header *)&io_out_ot_desc,
|
||||
|
||||
(struct usb_descriptor_header *)&ss_ep_int_desc,
|
||||
(struct usb_descriptor_header *)&ss_ep_int_desc,
|
||||
(struct usb_descriptor_header *)&ss_ep_int_desc_comp,
|
||||
|
||||
(struct usb_descriptor_header *)&std_as_out_if0_desc,
|
||||
(struct usb_descriptor_header *)&std_as_out_if1_desc,
|
||||
|
@ -800,6 +807,7 @@ static void setup_headers(struct f_uac2_opts *opts,
|
|||
struct usb_ss_ep_comp_descriptor *epout_desc_comp = NULL;
|
||||
struct usb_ss_ep_comp_descriptor *epin_desc_comp = NULL;
|
||||
struct usb_ss_ep_comp_descriptor *epin_fback_desc_comp = NULL;
|
||||
struct usb_ss_ep_comp_descriptor *ep_int_desc_comp = NULL;
|
||||
struct usb_endpoint_descriptor *epout_desc;
|
||||
struct usb_endpoint_descriptor *epin_desc;
|
||||
struct usb_endpoint_descriptor *epin_fback_desc;
|
||||
|
@ -827,6 +835,7 @@ static void setup_headers(struct f_uac2_opts *opts,
|
|||
epin_fback_desc = &ss_epin_fback_desc;
|
||||
epin_fback_desc_comp = &ss_epin_fback_desc_comp;
|
||||
ep_int_desc = &ss_ep_int_desc;
|
||||
ep_int_desc_comp = &ss_ep_int_desc_comp;
|
||||
}
|
||||
|
||||
i = 0;
|
||||
|
@ -855,8 +864,11 @@ static void setup_headers(struct f_uac2_opts *opts,
|
|||
if (EPOUT_EN(opts))
|
||||
headers[i++] = USBDHDR(&io_out_ot_desc);
|
||||
|
||||
if (FUOUT_EN(opts) || FUIN_EN(opts))
|
||||
if (FUOUT_EN(opts) || FUIN_EN(opts)) {
|
||||
headers[i++] = USBDHDR(ep_int_desc);
|
||||
if (ep_int_desc_comp)
|
||||
headers[i++] = USBDHDR(ep_int_desc_comp);
|
||||
}
|
||||
|
||||
if (EPOUT_EN(opts)) {
|
||||
headers[i++] = USBDHDR(&std_as_out_if0_desc);
|
||||
|
|
|
@ -294,8 +294,10 @@ EXPORT_SYMBOL_GPL(fsg_lun_fsync_sub);
|
|||
void store_cdrom_address(u8 *dest, int msf, u32 addr)
|
||||
{
|
||||
if (msf) {
|
||||
/* Convert to Minutes-Seconds-Frames */
|
||||
addr >>= 2; /* Convert to 2048-byte frames */
|
||||
/*
|
||||
* Convert to Minutes-Seconds-Frames.
|
||||
* Sector size is already set to 2048 bytes.
|
||||
*/
|
||||
addr += 2*75; /* Lead-in occupies 2 seconds */
|
||||
dest[3] = addr % 75; /* Frames */
|
||||
addr /= 75;
|
||||
|
|
|
@ -736,7 +736,10 @@ int usb_gadget_disconnect(struct usb_gadget *gadget)
|
|||
ret = gadget->ops->pullup(gadget, 0);
|
||||
if (!ret) {
|
||||
gadget->connected = 0;
|
||||
gadget->udc->driver->disconnect(gadget);
|
||||
mutex_lock(&udc_lock);
|
||||
if (gadget->udc->driver)
|
||||
gadget->udc->driver->disconnect(gadget);
|
||||
mutex_unlock(&udc_lock);
|
||||
}
|
||||
|
||||
out:
|
||||
|
@ -1489,7 +1492,6 @@ static int gadget_bind_driver(struct device *dev)
|
|||
|
||||
usb_gadget_udc_set_speed(udc, driver->max_speed);
|
||||
|
||||
mutex_lock(&udc_lock);
|
||||
ret = driver->bind(udc->gadget, driver);
|
||||
if (ret)
|
||||
goto err_bind;
|
||||
|
@ -1499,7 +1501,6 @@ static int gadget_bind_driver(struct device *dev)
|
|||
goto err_start;
|
||||
usb_gadget_enable_async_callbacks(udc);
|
||||
usb_udc_connect_control(udc);
|
||||
mutex_unlock(&udc_lock);
|
||||
|
||||
kobject_uevent(&udc->dev.kobj, KOBJ_CHANGE);
|
||||
return 0;
|
||||
|
@ -1512,6 +1513,7 @@ static int gadget_bind_driver(struct device *dev)
|
|||
dev_err(&udc->dev, "failed to start %s: %d\n",
|
||||
driver->function, ret);
|
||||
|
||||
mutex_lock(&udc_lock);
|
||||
udc->driver = NULL;
|
||||
driver->is_bound = false;
|
||||
mutex_unlock(&udc_lock);
|
||||
|
@ -1529,7 +1531,6 @@ static void gadget_unbind_driver(struct device *dev)
|
|||
|
||||
kobject_uevent(&udc->dev.kobj, KOBJ_CHANGE);
|
||||
|
||||
mutex_lock(&udc_lock);
|
||||
usb_gadget_disconnect(gadget);
|
||||
usb_gadget_disable_async_callbacks(udc);
|
||||
if (gadget->irq)
|
||||
|
@ -1537,6 +1538,7 @@ static void gadget_unbind_driver(struct device *dev)
|
|||
udc->driver->unbind(gadget);
|
||||
usb_gadget_udc_stop(udc);
|
||||
|
||||
mutex_lock(&udc_lock);
|
||||
driver->is_bound = false;
|
||||
udc->driver = NULL;
|
||||
mutex_unlock(&udc_lock);
|
||||
|
@ -1612,7 +1614,7 @@ static ssize_t soft_connect_store(struct device *dev,
|
|||
struct usb_udc *udc = container_of(dev, struct usb_udc, dev);
|
||||
ssize_t ret;
|
||||
|
||||
mutex_lock(&udc_lock);
|
||||
device_lock(&udc->gadget->dev);
|
||||
if (!udc->driver) {
|
||||
dev_err(dev, "soft-connect without a gadget driver\n");
|
||||
ret = -EOPNOTSUPP;
|
||||
|
@ -1633,7 +1635,7 @@ static ssize_t soft_connect_store(struct device *dev,
|
|||
|
||||
ret = n;
|
||||
out:
|
||||
mutex_unlock(&udc_lock);
|
||||
device_unlock(&udc->gadget->dev);
|
||||
return ret;
|
||||
}
|
||||
static DEVICE_ATTR_WO(soft_connect);
|
||||
|
@ -1652,11 +1654,15 @@ static ssize_t function_show(struct device *dev, struct device_attribute *attr,
|
|||
char *buf)
|
||||
{
|
||||
struct usb_udc *udc = container_of(dev, struct usb_udc, dev);
|
||||
struct usb_gadget_driver *drv = udc->driver;
|
||||
struct usb_gadget_driver *drv;
|
||||
int rc = 0;
|
||||
|
||||
if (!drv || !drv->function)
|
||||
return 0;
|
||||
return scnprintf(buf, PAGE_SIZE, "%s\n", drv->function);
|
||||
mutex_lock(&udc_lock);
|
||||
drv = udc->driver;
|
||||
if (drv && drv->function)
|
||||
rc = scnprintf(buf, PAGE_SIZE, "%s\n", drv->function);
|
||||
mutex_unlock(&udc_lock);
|
||||
return rc;
|
||||
}
|
||||
static DEVICE_ATTR_RO(function);
|
||||
|
||||
|
|
|
@ -652,7 +652,7 @@ struct xhci_hub *xhci_get_rhub(struct usb_hcd *hcd)
|
|||
* It will release and re-aquire the lock while calling ACPI
|
||||
* method.
|
||||
*/
|
||||
void xhci_set_port_power(struct xhci_hcd *xhci, struct usb_hcd *hcd,
|
||||
static void xhci_set_port_power(struct xhci_hcd *xhci, struct usb_hcd *hcd,
|
||||
u16 index, bool on, unsigned long *flags)
|
||||
__must_hold(&xhci->lock)
|
||||
{
|
||||
|
@ -1648,6 +1648,17 @@ int xhci_hub_status_data(struct usb_hcd *hcd, char *buf)
|
|||
|
||||
status = bus_state->resuming_ports;
|
||||
|
||||
/*
|
||||
* SS devices are only visible to roothub after link training completes.
|
||||
* Keep polling roothubs for a grace period after xHC start
|
||||
*/
|
||||
if (xhci->run_graceperiod) {
|
||||
if (time_before(jiffies, xhci->run_graceperiod))
|
||||
status = 1;
|
||||
else
|
||||
xhci->run_graceperiod = 0;
|
||||
}
|
||||
|
||||
mask = PORT_CSC | PORT_PEC | PORT_OCC | PORT_PLC | PORT_WRC | PORT_CEC;
|
||||
|
||||
/* For each port, did anything change? If so, set that bit in buf. */
|
||||
|
|
|
@ -425,7 +425,6 @@ static int check_fs_bus_bw(struct mu3h_sch_ep_info *sch_ep, int offset)
|
|||
|
||||
static int check_sch_tt(struct mu3h_sch_ep_info *sch_ep, u32 offset)
|
||||
{
|
||||
u32 extra_cs_count;
|
||||
u32 start_ss, last_ss;
|
||||
u32 start_cs, last_cs;
|
||||
|
||||
|
@ -461,18 +460,12 @@ static int check_sch_tt(struct mu3h_sch_ep_info *sch_ep, u32 offset)
|
|||
if (last_cs > 7)
|
||||
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 = 1;
|
||||
|
||||
cs_count += extra_cs_count;
|
||||
if (cs_count > 7)
|
||||
cs_count = 7; /* HW limit */
|
||||
|
||||
sch_ep->cs_count = cs_count;
|
||||
/* one for ss, the other for idle */
|
||||
sch_ep->num_budget_microframes = cs_count + 2;
|
||||
/* ss, idle are ignored */
|
||||
sch_ep->num_budget_microframes = cs_count;
|
||||
|
||||
/*
|
||||
* if interval=1, maxp >752, num_budge_micoframe is larger
|
||||
|
@ -771,8 +764,8 @@ int xhci_mtk_drop_ep(struct usb_hcd *hcd, struct usb_device *udev,
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (ep->hcpriv)
|
||||
drop_ep_quirk(hcd, udev, ep);
|
||||
/* needn't check @ep->hcpriv, xhci_endpoint_disable set it NULL */
|
||||
drop_ep_quirk(hcd, udev, ep);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -398,12 +398,17 @@ static int xhci_plat_remove(struct platform_device *dev)
|
|||
pm_runtime_get_sync(&dev->dev);
|
||||
xhci->xhc_state |= XHCI_STATE_REMOVING;
|
||||
|
||||
usb_remove_hcd(shared_hcd);
|
||||
xhci->shared_hcd = NULL;
|
||||
if (shared_hcd) {
|
||||
usb_remove_hcd(shared_hcd);
|
||||
xhci->shared_hcd = NULL;
|
||||
}
|
||||
|
||||
usb_phy_shutdown(hcd->usb_phy);
|
||||
|
||||
usb_remove_hcd(hcd);
|
||||
usb_put_hcd(shared_hcd);
|
||||
|
||||
if (shared_hcd)
|
||||
usb_put_hcd(shared_hcd);
|
||||
|
||||
clk_disable_unprepare(clk);
|
||||
clk_disable_unprepare(reg_clk);
|
||||
|
|
|
@ -151,9 +151,11 @@ int xhci_start(struct xhci_hcd *xhci)
|
|||
xhci_err(xhci, "Host took too long to start, "
|
||||
"waited %u microseconds.\n",
|
||||
XHCI_MAX_HALT_USEC);
|
||||
if (!ret)
|
||||
if (!ret) {
|
||||
/* clear state flags. Including dying, halted or removing */
|
||||
xhci->xhc_state = 0;
|
||||
xhci->run_graceperiod = jiffies + msecs_to_jiffies(500);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -791,8 +793,6 @@ static void xhci_stop(struct usb_hcd *hcd)
|
|||
void xhci_shutdown(struct usb_hcd *hcd)
|
||||
{
|
||||
struct xhci_hcd *xhci = hcd_to_xhci(hcd);
|
||||
unsigned long flags;
|
||||
int i;
|
||||
|
||||
if (xhci->quirks & XHCI_SPURIOUS_REBOOT)
|
||||
usb_disable_xhci_ports(to_pci_dev(hcd->self.sysdev));
|
||||
|
@ -808,21 +808,12 @@ void xhci_shutdown(struct usb_hcd *hcd)
|
|||
del_timer_sync(&xhci->shared_hcd->rh_timer);
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&xhci->lock, flags);
|
||||
spin_lock_irq(&xhci->lock);
|
||||
xhci_halt(xhci);
|
||||
|
||||
/* Power off USB2 ports*/
|
||||
for (i = 0; i < xhci->usb2_rhub.num_ports; i++)
|
||||
xhci_set_port_power(xhci, xhci->main_hcd, i, false, &flags);
|
||||
|
||||
/* Power off USB3 ports*/
|
||||
for (i = 0; i < xhci->usb3_rhub.num_ports; i++)
|
||||
xhci_set_port_power(xhci, xhci->shared_hcd, i, false, &flags);
|
||||
|
||||
/* Workaround for spurious wakeups at shutdown with HSW */
|
||||
if (xhci->quirks & XHCI_SPURIOUS_WAKEUP)
|
||||
xhci_reset(xhci, XHCI_RESET_SHORT_USEC);
|
||||
spin_unlock_irqrestore(&xhci->lock, flags);
|
||||
spin_unlock_irq(&xhci->lock);
|
||||
|
||||
xhci_cleanup_msix(xhci);
|
||||
|
||||
|
|
|
@ -1826,7 +1826,7 @@ struct xhci_hcd {
|
|||
|
||||
/* Host controller watchdog timer structures */
|
||||
unsigned int xhc_state;
|
||||
|
||||
unsigned long run_graceperiod;
|
||||
u32 command;
|
||||
struct s3_save s3;
|
||||
/* Host controller is dying - not responding to commands. "I'm not dead yet!"
|
||||
|
@ -2196,8 +2196,6 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, u16 wIndex,
|
|||
int xhci_hub_status_data(struct usb_hcd *hcd, char *buf);
|
||||
int xhci_find_raw_port_number(struct usb_hcd *hcd, int port1);
|
||||
struct xhci_hub *xhci_get_rhub(struct usb_hcd *hcd);
|
||||
void xhci_set_port_power(struct xhci_hcd *xhci, struct usb_hcd *hcd, u16 index,
|
||||
bool on, unsigned long *flags);
|
||||
|
||||
void xhci_hc_died(struct xhci_hcd *xhci);
|
||||
|
||||
|
|
|
@ -71,10 +71,7 @@ static int onboard_hub_power_off(struct onboard_hub *hub)
|
|||
{
|
||||
int err;
|
||||
|
||||
if (hub->reset_gpio) {
|
||||
gpiod_set_value_cansleep(hub->reset_gpio, 1);
|
||||
fsleep(hub->pdata->reset_us);
|
||||
}
|
||||
gpiod_set_value_cansleep(hub->reset_gpio, 1);
|
||||
|
||||
err = regulator_disable(hub->vdd);
|
||||
if (err) {
|
||||
|
|
|
@ -86,7 +86,7 @@ config USB_MUSB_TUSB6010
|
|||
tristate "TUSB6010"
|
||||
depends on HAS_IOMEM
|
||||
depends on ARCH_OMAP2PLUS || COMPILE_TEST
|
||||
depends on NOP_USB_XCEIV = USB_MUSB_HDRC # both built-in or both modules
|
||||
depends on NOP_USB_XCEIV!=m || USB_MUSB_HDRC=m
|
||||
|
||||
config USB_MUSB_OMAP2PLUS
|
||||
tristate "OMAP2430 and onwards"
|
||||
|
|
|
@ -97,7 +97,10 @@ struct ch341_private {
|
|||
u8 mcr;
|
||||
u8 msr;
|
||||
u8 lcr;
|
||||
|
||||
unsigned long quirks;
|
||||
u8 version;
|
||||
|
||||
unsigned long break_end;
|
||||
};
|
||||
|
||||
|
@ -250,8 +253,12 @@ static int ch341_set_baudrate_lcr(struct usb_device *dev,
|
|||
/*
|
||||
* CH341A buffers data until a full endpoint-size packet (32 bytes)
|
||||
* has been received unless bit 7 is set.
|
||||
*
|
||||
* At least one device with version 0x27 appears to have this bit
|
||||
* inverted.
|
||||
*/
|
||||
val |= BIT(7);
|
||||
if (priv->version > 0x27)
|
||||
val |= BIT(7);
|
||||
|
||||
r = ch341_control_out(dev, CH341_REQ_WRITE_REG,
|
||||
CH341_REG_DIVISOR << 8 | CH341_REG_PRESCALER,
|
||||
|
@ -265,6 +272,9 @@ static int ch341_set_baudrate_lcr(struct usb_device *dev,
|
|||
* (stop bits, parity and word length). Version 0x30 and above use
|
||||
* CH341_REG_LCR only and CH341_REG_LCR2 is always set to zero.
|
||||
*/
|
||||
if (priv->version < 0x30)
|
||||
return 0;
|
||||
|
||||
r = ch341_control_out(dev, CH341_REQ_WRITE_REG,
|
||||
CH341_REG_LCR2 << 8 | CH341_REG_LCR, lcr);
|
||||
if (r)
|
||||
|
@ -308,7 +318,9 @@ static int ch341_configure(struct usb_device *dev, struct ch341_private *priv)
|
|||
r = ch341_control_in(dev, CH341_REQ_READ_VERSION, 0, 0, buffer, size);
|
||||
if (r)
|
||||
return r;
|
||||
dev_dbg(&dev->dev, "Chip version: 0x%02x\n", buffer[0]);
|
||||
|
||||
priv->version = buffer[0];
|
||||
dev_dbg(&dev->dev, "Chip version: 0x%02x\n", priv->version);
|
||||
|
||||
r = ch341_control_out(dev, CH341_REQ_SERIAL_INIT, 0, 0);
|
||||
if (r < 0)
|
||||
|
|
|
@ -130,6 +130,7 @@ static const struct usb_device_id id_table[] = {
|
|||
{ USB_DEVICE(0x10C4, 0x83AA) }, /* Mark-10 Digital Force Gauge */
|
||||
{ USB_DEVICE(0x10C4, 0x83D8) }, /* DekTec DTA Plus VHF/UHF Booster/Attenuator */
|
||||
{ USB_DEVICE(0x10C4, 0x8411) }, /* Kyocera GPS Module */
|
||||
{ USB_DEVICE(0x10C4, 0x8414) }, /* Decagon USB Cable Adapter */
|
||||
{ USB_DEVICE(0x10C4, 0x8418) }, /* IRZ Automation Teleport SG-10 GSM/GPRS Modem */
|
||||
{ USB_DEVICE(0x10C4, 0x846E) }, /* BEI USB Sensor Interface (VCP) */
|
||||
{ USB_DEVICE(0x10C4, 0x8470) }, /* Juniper Networks BX Series System Console */
|
||||
|
|
|
@ -1045,6 +1045,8 @@ static const struct usb_device_id id_table_combined[] = {
|
|||
/* IDS GmbH devices */
|
||||
{ USB_DEVICE(IDS_VID, IDS_SI31A_PID) },
|
||||
{ USB_DEVICE(IDS_VID, IDS_CM31A_PID) },
|
||||
/* Omron devices */
|
||||
{ USB_DEVICE(OMRON_VID, OMRON_CS1W_CIF31_PID) },
|
||||
/* U-Blox devices */
|
||||
{ USB_DEVICE(UBLOX_VID, UBLOX_C099F9P_ZED_PID) },
|
||||
{ USB_DEVICE(UBLOX_VID, UBLOX_C099F9P_ODIN_PID) },
|
||||
|
|
|
@ -661,6 +661,12 @@
|
|||
#define INFINEON_TRIBOARD_TC1798_PID 0x0028 /* DAS JTAG TriBoard TC1798 V1.0 */
|
||||
#define INFINEON_TRIBOARD_TC2X7_PID 0x0043 /* DAS JTAG TriBoard TC2X7 V1.0 */
|
||||
|
||||
/*
|
||||
* Omron corporation (https://www.omron.com)
|
||||
*/
|
||||
#define OMRON_VID 0x0590
|
||||
#define OMRON_CS1W_CIF31_PID 0x00b2
|
||||
|
||||
/*
|
||||
* Acton Research Corp.
|
||||
*/
|
||||
|
|
|
@ -253,6 +253,7 @@ static void option_instat_callback(struct urb *urb);
|
|||
#define QUECTEL_PRODUCT_BG96 0x0296
|
||||
#define QUECTEL_PRODUCT_EP06 0x0306
|
||||
#define QUECTEL_PRODUCT_EM05G 0x030a
|
||||
#define QUECTEL_PRODUCT_EM060K 0x030b
|
||||
#define QUECTEL_PRODUCT_EM12 0x0512
|
||||
#define QUECTEL_PRODUCT_RM500Q 0x0800
|
||||
#define QUECTEL_PRODUCT_EC200S_CN 0x6002
|
||||
|
@ -438,6 +439,8 @@ static void option_instat_callback(struct urb *urb);
|
|||
#define CINTERION_PRODUCT_MV31_2_RMNET 0x00b9
|
||||
#define CINTERION_PRODUCT_MV32_WA 0x00f1
|
||||
#define CINTERION_PRODUCT_MV32_WB 0x00f2
|
||||
#define CINTERION_PRODUCT_MV32_WA_RMNET 0x00f3
|
||||
#define CINTERION_PRODUCT_MV32_WB_RMNET 0x00f4
|
||||
|
||||
/* Olivetti products */
|
||||
#define OLIVETTI_VENDOR_ID 0x0b3c
|
||||
|
@ -573,6 +576,10 @@ static void option_instat_callback(struct urb *urb);
|
|||
#define WETELECOM_PRODUCT_6802 0x6802
|
||||
#define WETELECOM_PRODUCT_WMD300 0x6803
|
||||
|
||||
/* OPPO products */
|
||||
#define OPPO_VENDOR_ID 0x22d9
|
||||
#define OPPO_PRODUCT_R11 0x276c
|
||||
|
||||
|
||||
/* Device flags */
|
||||
|
||||
|
@ -1138,6 +1145,9 @@ static const struct usb_device_id option_ids[] = {
|
|||
{ USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EP06, 0xff, 0, 0) },
|
||||
{ USB_DEVICE_INTERFACE_CLASS(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EM05G, 0xff),
|
||||
.driver_info = RSVD(6) | ZLP },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EM060K, 0xff, 0x00, 0x40) },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EM060K, 0xff, 0xff, 0x30) },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EM060K, 0xff, 0xff, 0x40) },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EM12, 0xff, 0xff, 0xff),
|
||||
.driver_info = RSVD(1) | RSVD(2) | RSVD(3) | RSVD(4) | NUMEP2 },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EM12, 0xff, 0, 0) },
|
||||
|
@ -1993,8 +2003,12 @@ static const struct usb_device_id option_ids[] = {
|
|||
.driver_info = RSVD(0)},
|
||||
{ USB_DEVICE_INTERFACE_CLASS(CINTERION_VENDOR_ID, CINTERION_PRODUCT_MV32_WA, 0xff),
|
||||
.driver_info = RSVD(3)},
|
||||
{ USB_DEVICE_INTERFACE_CLASS(CINTERION_VENDOR_ID, CINTERION_PRODUCT_MV32_WA_RMNET, 0xff),
|
||||
.driver_info = RSVD(0) },
|
||||
{ USB_DEVICE_INTERFACE_CLASS(CINTERION_VENDOR_ID, CINTERION_PRODUCT_MV32_WB, 0xff),
|
||||
.driver_info = RSVD(3)},
|
||||
{ USB_DEVICE_INTERFACE_CLASS(CINTERION_VENDOR_ID, CINTERION_PRODUCT_MV32_WB_RMNET, 0xff),
|
||||
.driver_info = RSVD(0) },
|
||||
{ USB_DEVICE(OLIVETTI_VENDOR_ID, OLIVETTI_PRODUCT_OLICARD100),
|
||||
.driver_info = RSVD(4) },
|
||||
{ USB_DEVICE(OLIVETTI_VENDOR_ID, OLIVETTI_PRODUCT_OLICARD120),
|
||||
|
@ -2155,6 +2169,7 @@ static const struct usb_device_id option_ids[] = {
|
|||
{ USB_DEVICE_INTERFACE_CLASS(0x305a, 0x1404, 0xff) }, /* GosunCn GM500 RNDIS */
|
||||
{ USB_DEVICE_INTERFACE_CLASS(0x305a, 0x1405, 0xff) }, /* GosunCn GM500 MBIM */
|
||||
{ USB_DEVICE_INTERFACE_CLASS(0x305a, 0x1406, 0xff) }, /* GosunCn GM500 ECM/NCM */
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(OPPO_VENDOR_ID, OPPO_PRODUCT_R11, 0xff, 0xff, 0x30) },
|
||||
{ } /* Terminating entry */
|
||||
};
|
||||
MODULE_DEVICE_TABLE(usb, option_ids);
|
||||
|
|
|
@ -2294,6 +2294,13 @@ UNUSUAL_DEV( 0x1e74, 0x4621, 0x0000, 0x0000,
|
|||
USB_SC_DEVICE, USB_PR_DEVICE, NULL,
|
||||
US_FL_BULK_IGNORE_TAG | US_FL_MAX_SECTORS_64 ),
|
||||
|
||||
/* Reported by Witold Lipieta <witold.lipieta@thaumatec.com> */
|
||||
UNUSUAL_DEV( 0x1fc9, 0x0117, 0x0100, 0x0100,
|
||||
"NXP Semiconductors",
|
||||
"PN7462AU",
|
||||
USB_SC_DEVICE, USB_PR_DEVICE, NULL,
|
||||
US_FL_IGNORE_RESIDUE ),
|
||||
|
||||
/* Supplied with some Castlewood ORB removable drives */
|
||||
UNUSUAL_DEV( 0x2027, 0xa001, 0x0000, 0x9999,
|
||||
"Double-H Technology",
|
||||
|
|
|
@ -62,6 +62,13 @@ UNUSUAL_DEV(0x0984, 0x0301, 0x0128, 0x0128,
|
|||
USB_SC_DEVICE, USB_PR_DEVICE, NULL,
|
||||
US_FL_IGNORE_UAS),
|
||||
|
||||
/* Reported-by: Tom Hu <huxiaoying@kylinos.cn> */
|
||||
UNUSUAL_DEV(0x0b05, 0x1932, 0x0000, 0x9999,
|
||||
"ASUS",
|
||||
"External HDD",
|
||||
USB_SC_DEVICE, USB_PR_DEVICE, NULL,
|
||||
US_FL_IGNORE_UAS),
|
||||
|
||||
/* Reported-by: David Webb <djw@noc.ac.uk> */
|
||||
UNUSUAL_DEV(0x0bc2, 0x331a, 0x0000, 0x9999,
|
||||
"Seagate",
|
||||
|
|
|
@ -99,8 +99,8 @@ static int dp_altmode_configure(struct dp_altmode *dp, u8 con)
|
|||
case DP_STATUS_CON_UFP_D:
|
||||
case DP_STATUS_CON_BOTH: /* NOTE: First acting as DP source */
|
||||
conf |= DP_CONF_UFP_U_AS_UFP_D;
|
||||
pin_assign = DP_CAP_DFP_D_PIN_ASSIGN(dp->alt->vdo) &
|
||||
DP_CAP_UFP_D_PIN_ASSIGN(dp->port->vdo);
|
||||
pin_assign = DP_CAP_PIN_ASSIGN_UFP_D(dp->alt->vdo) &
|
||||
DP_CAP_PIN_ASSIGN_DFP_D(dp->port->vdo);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
|
|
@ -2346,6 +2346,7 @@ static void __exit typec_exit(void)
|
|||
ida_destroy(&typec_index_ida);
|
||||
bus_unregister(&typec_bus);
|
||||
class_unregister(&typec_mux_class);
|
||||
class_unregister(&retimer_class);
|
||||
}
|
||||
module_exit(typec_exit);
|
||||
|
||||
|
|
|
@ -571,9 +571,11 @@ static int pmc_usb_register_port(struct pmc_usb *pmc, int index,
|
|||
|
||||
static int is_memory(struct acpi_resource *res, void *data)
|
||||
{
|
||||
struct resource r;
|
||||
struct resource_win win = {};
|
||||
struct resource *r = &win.res;
|
||||
|
||||
return !acpi_dev_resource_memory(res, &r);
|
||||
return !(acpi_dev_resource_memory(res, r) ||
|
||||
acpi_dev_resource_address_space(res, &win));
|
||||
}
|
||||
|
||||
/* IOM ACPI IDs and IOM_PORT_STATUS_OFFSET */
|
||||
|
@ -583,6 +585,9 @@ static const struct acpi_device_id iom_acpi_ids[] = {
|
|||
|
||||
/* AlderLake */
|
||||
{ "INTC1079", 0x160, },
|
||||
|
||||
/* Meteor Lake */
|
||||
{ "INTC107A", 0x160, },
|
||||
{}
|
||||
};
|
||||
|
||||
|
|
|
@ -6320,6 +6320,13 @@ static int tcpm_psy_set_prop(struct power_supply *psy,
|
|||
struct tcpm_port *port = power_supply_get_drvdata(psy);
|
||||
int ret;
|
||||
|
||||
/*
|
||||
* All the properties below are related to USB PD. The check needs to be
|
||||
* property specific when a non-pd related property is added.
|
||||
*/
|
||||
if (!port->pd_supported)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
switch (psp) {
|
||||
case POWER_SUPPLY_PROP_ONLINE:
|
||||
ret = tcpm_psy_set_online(port, val);
|
||||
|
|
|
@ -1200,32 +1200,6 @@ static int ucsi_register_port(struct ucsi *ucsi, int index)
|
|||
return ret;
|
||||
}
|
||||
|
||||
static void ucsi_unregister_connectors(struct ucsi *ucsi)
|
||||
{
|
||||
struct ucsi_connector *con;
|
||||
int i;
|
||||
|
||||
if (!ucsi->connector)
|
||||
return;
|
||||
|
||||
for (i = 0; i < ucsi->cap.num_connectors; i++) {
|
||||
con = &ucsi->connector[i];
|
||||
|
||||
if (!con->wq)
|
||||
break;
|
||||
|
||||
cancel_work_sync(&con->work);
|
||||
ucsi_unregister_partner(con);
|
||||
ucsi_unregister_altmodes(con, UCSI_RECIPIENT_CON);
|
||||
ucsi_unregister_port_psy(con);
|
||||
destroy_workqueue(con->wq);
|
||||
typec_unregister_port(con->port);
|
||||
}
|
||||
|
||||
kfree(ucsi->connector);
|
||||
ucsi->connector = NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* ucsi_init - Initialize UCSI interface
|
||||
* @ucsi: UCSI to be initialized
|
||||
|
@ -1234,6 +1208,7 @@ static void ucsi_unregister_connectors(struct ucsi *ucsi)
|
|||
*/
|
||||
static int ucsi_init(struct ucsi *ucsi)
|
||||
{
|
||||
struct ucsi_connector *con;
|
||||
u64 command;
|
||||
int ret;
|
||||
int i;
|
||||
|
@ -1264,7 +1239,7 @@ static int ucsi_init(struct ucsi *ucsi)
|
|||
}
|
||||
|
||||
/* Allocate the connectors. Released in ucsi_unregister() */
|
||||
ucsi->connector = kcalloc(ucsi->cap.num_connectors,
|
||||
ucsi->connector = kcalloc(ucsi->cap.num_connectors + 1,
|
||||
sizeof(*ucsi->connector), GFP_KERNEL);
|
||||
if (!ucsi->connector) {
|
||||
ret = -ENOMEM;
|
||||
|
@ -1288,7 +1263,15 @@ static int ucsi_init(struct ucsi *ucsi)
|
|||
return 0;
|
||||
|
||||
err_unregister:
|
||||
ucsi_unregister_connectors(ucsi);
|
||||
for (con = ucsi->connector; con->port; con++) {
|
||||
ucsi_unregister_partner(con);
|
||||
ucsi_unregister_altmodes(con, UCSI_RECIPIENT_CON);
|
||||
ucsi_unregister_port_psy(con);
|
||||
if (con->wq)
|
||||
destroy_workqueue(con->wq);
|
||||
typec_unregister_port(con->port);
|
||||
con->port = NULL;
|
||||
}
|
||||
|
||||
err_reset:
|
||||
memset(&ucsi->cap, 0, sizeof(ucsi->cap));
|
||||
|
@ -1402,6 +1385,7 @@ EXPORT_SYMBOL_GPL(ucsi_register);
|
|||
void ucsi_unregister(struct ucsi *ucsi)
|
||||
{
|
||||
u64 cmd = UCSI_SET_NOTIFICATION_ENABLE;
|
||||
int i;
|
||||
|
||||
/* Make sure that we are not in the middle of driver initialization */
|
||||
cancel_delayed_work_sync(&ucsi->work);
|
||||
|
@ -1409,7 +1393,18 @@ void ucsi_unregister(struct ucsi *ucsi)
|
|||
/* Disable notifications */
|
||||
ucsi->ops->async_write(ucsi, UCSI_CONTROL, &cmd, sizeof(cmd));
|
||||
|
||||
ucsi_unregister_connectors(ucsi);
|
||||
for (i = 0; i < ucsi->cap.num_connectors; i++) {
|
||||
cancel_work_sync(&ucsi->connector[i].work);
|
||||
ucsi_unregister_partner(&ucsi->connector[i]);
|
||||
ucsi_unregister_altmodes(&ucsi->connector[i],
|
||||
UCSI_RECIPIENT_CON);
|
||||
ucsi_unregister_port_psy(&ucsi->connector[i]);
|
||||
if (ucsi->connector[i].wq)
|
||||
destroy_workqueue(ucsi->connector[i].wq);
|
||||
typec_unregister_port(ucsi->connector[i].port);
|
||||
}
|
||||
|
||||
kfree(ucsi->connector);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ucsi_unregister);
|
||||
|
||||
|
|
|
@ -575,6 +575,7 @@ struct usb3_lpm_parameters {
|
|||
* @devaddr: device address, XHCI: assigned by HW, others: same as devnum
|
||||
* @can_submit: URBs may be submitted
|
||||
* @persist_enabled: USB_PERSIST enabled for this device
|
||||
* @reset_in_progress: the device is being reset
|
||||
* @have_langid: whether string_langid is valid
|
||||
* @authorized: policy has said we can use it;
|
||||
* (user space) policy determines if we authorize this device to be
|
||||
|
@ -662,6 +663,7 @@ struct usb_device {
|
|||
|
||||
unsigned can_submit:1;
|
||||
unsigned persist_enabled:1;
|
||||
unsigned reset_in_progress:1;
|
||||
unsigned have_langid:1;
|
||||
unsigned authorized:1;
|
||||
unsigned authenticated:1;
|
||||
|
|
|
@ -73,6 +73,11 @@ enum {
|
|||
#define DP_CAP_USB BIT(7)
|
||||
#define DP_CAP_DFP_D_PIN_ASSIGN(_cap_) (((_cap_) & GENMASK(15, 8)) >> 8)
|
||||
#define DP_CAP_UFP_D_PIN_ASSIGN(_cap_) (((_cap_) & GENMASK(23, 16)) >> 16)
|
||||
/* Get pin assignment taking plug & receptacle into consideration */
|
||||
#define DP_CAP_PIN_ASSIGN_UFP_D(_cap_) ((_cap_ & DP_CAP_RECEPTACLE) ? \
|
||||
DP_CAP_UFP_D_PIN_ASSIGN(_cap_) : DP_CAP_DFP_D_PIN_ASSIGN(_cap_))
|
||||
#define DP_CAP_PIN_ASSIGN_DFP_D(_cap_) ((_cap_ & DP_CAP_RECEPTACLE) ? \
|
||||
DP_CAP_DFP_D_PIN_ASSIGN(_cap_) : DP_CAP_UFP_D_PIN_ASSIGN(_cap_))
|
||||
|
||||
/* DisplayPort Status Update VDO bits */
|
||||
#define DP_STATUS_CONNECTION(_status_) ((_status_) & 3)
|
||||
|
|
Loading…
Reference in a new issue