mirror of
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-03-22 07:27:12 +08:00
Merge tag 'usb-6.19-rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb
Pull USB fixes from Greg KH:
"Here are some small USB fixes and new device ids for 6.19-rc6
Included in here are:
- new usb-serial device ids
- dwc3-apple driver fixes to get things working properly on that
hardware platform
- ohci/uhci platfrom driver module soft-deps with ehci to remove a
runtime warning that sometimes shows up on some platforms.
- quirk for broken devices that can not handle reading the BOS
descriptor from them without going crazy.
- usb-serial driver fixes
- xhci driver fixes
- usb gadget driver fixes
All of these except for the last xhci fix has been in linux-next for a
while. The xhci fix has been reported by others to solve the issue for
them, so should be ok"
* tag 'usb-6.19-rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb:
xhci: sideband: don't dereference freed ring when removing sideband endpoint
usb: gadget: uvc: retry vb2_reqbufs() with vb_vmalloc_memops if use_sg fail
usb: gadget: uvc: return error from uvcg_queue_init()
usb: gadget: uvc: fix interval_duration calculation
usb: gadget: uvc: fix req_payload_size calculation
usb: dwc3: apple: Ignore USB role switches to the active role
usb: host: xhci-tegra: Use platform_get_irq_optional() for wake IRQs
USB: OHCI/UHCI: Add soft dependencies on ehci_platform
usb: dwc3: apple: Set USB2 PHY mode before dwc3 init
USB: serial: f81232: fix incomplete serial port generation
USB: serial: ftdi_sio: add support for PICAXE AXE027 cable
USB: serial: option: add Telit LE910 MBIM composition
usb: core: add USB_QUIRK_NO_BOS for devices that hang on BOS descriptor
dt-bindings: usb: qcom,dwc3: Correct MSM8994 interrupts
dt-bindings: usb: qcom,dwc3: Correct IPQ5018 interrupts
tcpm: allow looking for role_sw device in the main node
usb: dwc3: Check for USB4 IP_NAME
This commit is contained in:
@@ -406,7 +406,6 @@ allOf:
|
||||
compatible:
|
||||
contains:
|
||||
enum:
|
||||
- qcom,ipq5018-dwc3
|
||||
- qcom,ipq6018-dwc3
|
||||
- qcom,ipq8074-dwc3
|
||||
- qcom,msm8953-dwc3
|
||||
@@ -428,6 +427,7 @@ allOf:
|
||||
compatible:
|
||||
contains:
|
||||
enum:
|
||||
- qcom,msm8994-dwc3
|
||||
- qcom,msm8996-dwc3
|
||||
- qcom,qcs404-dwc3
|
||||
- qcom,sdm660-dwc3
|
||||
@@ -451,6 +451,7 @@ allOf:
|
||||
compatible:
|
||||
contains:
|
||||
enum:
|
||||
- qcom,ipq5018-dwc3
|
||||
- qcom,ipq5332-dwc3
|
||||
then:
|
||||
properties:
|
||||
@@ -488,7 +489,6 @@ allOf:
|
||||
enum:
|
||||
- qcom,ipq4019-dwc3
|
||||
- qcom,ipq8064-dwc3
|
||||
- qcom,msm8994-dwc3
|
||||
- qcom,qcs615-dwc3
|
||||
- qcom,qcs8300-dwc3
|
||||
- qcom,qdu1000-dwc3
|
||||
|
||||
@@ -420,7 +420,6 @@ allOf:
|
||||
compatible:
|
||||
contains:
|
||||
enum:
|
||||
- qcom,ipq5018-dwc3
|
||||
- qcom,ipq6018-dwc3
|
||||
- qcom,ipq8074-dwc3
|
||||
- qcom,msm8953-dwc3
|
||||
@@ -443,6 +442,7 @@ allOf:
|
||||
compatible:
|
||||
contains:
|
||||
enum:
|
||||
- qcom,msm8994-dwc3
|
||||
- qcom,msm8996-dwc3
|
||||
- qcom,qcs404-dwc3
|
||||
- qcom,sdm660-dwc3
|
||||
@@ -467,6 +467,7 @@ allOf:
|
||||
compatible:
|
||||
contains:
|
||||
enum:
|
||||
- qcom,ipq5018-dwc3
|
||||
- qcom,ipq5332-dwc3
|
||||
then:
|
||||
properties:
|
||||
@@ -509,7 +510,6 @@ allOf:
|
||||
- qcom,ipq4019-dwc3
|
||||
- qcom,ipq8064-dwc3
|
||||
- qcom,kaanapali-dwc3
|
||||
- qcom,msm8994-dwc3
|
||||
- qcom,qcs615-dwc3
|
||||
- qcom,qcs8300-dwc3
|
||||
- qcom,qdu1000-dwc3
|
||||
|
||||
@@ -1040,6 +1040,11 @@ int usb_get_bos_descriptor(struct usb_device *dev)
|
||||
__u8 cap_type;
|
||||
int ret;
|
||||
|
||||
if (dev->quirks & USB_QUIRK_NO_BOS) {
|
||||
dev_dbg(ddev, "skipping BOS descriptor\n");
|
||||
return -ENOMSG;
|
||||
}
|
||||
|
||||
bos = kzalloc(sizeof(*bos), GFP_KERNEL);
|
||||
if (!bos)
|
||||
return -ENOMEM;
|
||||
|
||||
@@ -450,6 +450,9 @@ static const struct usb_device_id usb_quirk_list[] = {
|
||||
{ USB_DEVICE(0x0c45, 0x7056), .driver_info =
|
||||
USB_QUIRK_IGNORE_REMOTE_WAKEUP },
|
||||
|
||||
/* Elgato 4K X - BOS descriptor fetch hangs at SuperSpeed Plus */
|
||||
{ USB_DEVICE(0x0fd9, 0x009b), .driver_info = USB_QUIRK_NO_BOS },
|
||||
|
||||
/* Sony Xperia XZ1 Compact (lilac) smartphone in fastboot mode */
|
||||
{ USB_DEVICE(0x0fce, 0x0dde), .driver_info = USB_QUIRK_NO_LPM },
|
||||
|
||||
|
||||
@@ -993,6 +993,8 @@ static bool dwc3_core_is_valid(struct dwc3 *dwc)
|
||||
|
||||
reg = dwc3_readl(dwc->regs, DWC3_GSNPSID);
|
||||
dwc->ip = DWC3_GSNPS_ID(reg);
|
||||
if (dwc->ip == DWC4_IP)
|
||||
dwc->ip = DWC32_IP;
|
||||
|
||||
/* This should read as U3 followed by revision number */
|
||||
if (DWC3_IP_IS(DWC3)) {
|
||||
|
||||
@@ -1265,6 +1265,7 @@ struct dwc3 {
|
||||
#define DWC3_IP 0x5533
|
||||
#define DWC31_IP 0x3331
|
||||
#define DWC32_IP 0x3332
|
||||
#define DWC4_IP 0x3430
|
||||
|
||||
u32 revision;
|
||||
|
||||
|
||||
@@ -218,25 +218,31 @@ static int dwc3_apple_core_init(struct dwc3_apple *appledwc)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void dwc3_apple_phy_set_mode(struct dwc3_apple *appledwc, enum phy_mode mode)
|
||||
{
|
||||
lockdep_assert_held(&appledwc->lock);
|
||||
|
||||
/*
|
||||
* This platform requires SUSPHY to be enabled here already in order to properly configure
|
||||
* the PHY and switch dwc3's PIPE interface to USB3 PHY.
|
||||
*/
|
||||
dwc3_enable_susphy(&appledwc->dwc, true);
|
||||
phy_set_mode(appledwc->dwc.usb2_generic_phy[0], mode);
|
||||
phy_set_mode(appledwc->dwc.usb3_generic_phy[0], mode);
|
||||
}
|
||||
|
||||
static int dwc3_apple_init(struct dwc3_apple *appledwc, enum dwc3_apple_state state)
|
||||
{
|
||||
int ret, ret_reset;
|
||||
|
||||
lockdep_assert_held(&appledwc->lock);
|
||||
|
||||
/*
|
||||
* The USB2 PHY on this platform must be configured for host or device mode while it is
|
||||
* still powered off and before dwc3 tries to access it. Otherwise, the new configuration
|
||||
* will sometimes only take affect after the *next* time dwc3 is brought up which causes
|
||||
* the connected device to just not work.
|
||||
* The USB3 PHY must be configured later after dwc3 has already been initialized.
|
||||
*/
|
||||
switch (state) {
|
||||
case DWC3_APPLE_HOST:
|
||||
phy_set_mode(appledwc->dwc.usb2_generic_phy[0], PHY_MODE_USB_HOST);
|
||||
break;
|
||||
case DWC3_APPLE_DEVICE:
|
||||
phy_set_mode(appledwc->dwc.usb2_generic_phy[0], PHY_MODE_USB_DEVICE);
|
||||
break;
|
||||
default:
|
||||
/* Unreachable unless there's a bug in this driver */
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = reset_control_deassert(appledwc->reset);
|
||||
if (ret) {
|
||||
dev_err(appledwc->dev, "Failed to deassert reset, err=%d\n", ret);
|
||||
@@ -257,7 +263,13 @@ static int dwc3_apple_init(struct dwc3_apple *appledwc, enum dwc3_apple_state st
|
||||
case DWC3_APPLE_HOST:
|
||||
appledwc->dwc.dr_mode = USB_DR_MODE_HOST;
|
||||
dwc3_apple_set_ptrcap(appledwc, DWC3_GCTL_PRTCAP_HOST);
|
||||
dwc3_apple_phy_set_mode(appledwc, PHY_MODE_USB_HOST);
|
||||
/*
|
||||
* This platform requires SUSPHY to be enabled here already in order to properly
|
||||
* configure the PHY and switch dwc3's PIPE interface to USB3 PHY. The USB2 PHY
|
||||
* has already been configured to the correct mode earlier.
|
||||
*/
|
||||
dwc3_enable_susphy(&appledwc->dwc, true);
|
||||
phy_set_mode(appledwc->dwc.usb3_generic_phy[0], PHY_MODE_USB_HOST);
|
||||
ret = dwc3_host_init(&appledwc->dwc);
|
||||
if (ret) {
|
||||
dev_err(appledwc->dev, "Failed to initialize host, ret=%d\n", ret);
|
||||
@@ -268,7 +280,13 @@ static int dwc3_apple_init(struct dwc3_apple *appledwc, enum dwc3_apple_state st
|
||||
case DWC3_APPLE_DEVICE:
|
||||
appledwc->dwc.dr_mode = USB_DR_MODE_PERIPHERAL;
|
||||
dwc3_apple_set_ptrcap(appledwc, DWC3_GCTL_PRTCAP_DEVICE);
|
||||
dwc3_apple_phy_set_mode(appledwc, PHY_MODE_USB_DEVICE);
|
||||
/*
|
||||
* This platform requires SUSPHY to be enabled here already in order to properly
|
||||
* configure the PHY and switch dwc3's PIPE interface to USB3 PHY. The USB2 PHY
|
||||
* has already been configured to the correct mode earlier.
|
||||
*/
|
||||
dwc3_enable_susphy(&appledwc->dwc, true);
|
||||
phy_set_mode(appledwc->dwc.usb3_generic_phy[0], PHY_MODE_USB_DEVICE);
|
||||
ret = dwc3_gadget_init(&appledwc->dwc);
|
||||
if (ret) {
|
||||
dev_err(appledwc->dev, "Failed to initialize gadget, ret=%d\n", ret);
|
||||
@@ -339,6 +357,22 @@ static int dwc3_usb_role_switch_set(struct usb_role_switch *sw, enum usb_role ro
|
||||
|
||||
guard(mutex)(&appledwc->lock);
|
||||
|
||||
/*
|
||||
* Skip role switches if appledwc is already in the desired state. The
|
||||
* USB-C port controller on M2 and M1/M2 Pro/Max/Ultra devices issues
|
||||
* additional interrupts which results in usb_role_switch_set_role()
|
||||
* calls with the current role.
|
||||
* Ignore those calls here to ensure the USB-C port controller and
|
||||
* appledwc are in a consistent state.
|
||||
* This matches the behaviour in __dwc3_set_mode().
|
||||
* Do no handle USB_ROLE_NONE for DWC3_APPLE_NO_CABLE and
|
||||
* DWC3_APPLE_PROBE_PENDING since that is no-op anyway.
|
||||
*/
|
||||
if (appledwc->state == DWC3_APPLE_HOST && role == USB_ROLE_HOST)
|
||||
return 0;
|
||||
if (appledwc->state == DWC3_APPLE_DEVICE && role == USB_ROLE_DEVICE)
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* We need to tear all of dwc3 down and re-initialize it every time a cable is
|
||||
* connected or disconnected or when the mode changes. See the documentation for enum
|
||||
|
||||
@@ -362,6 +362,10 @@ uvc_function_set_alt(struct usb_function *f, unsigned interface, unsigned alt)
|
||||
return ret;
|
||||
usb_ep_enable(uvc->video.ep);
|
||||
|
||||
uvc->video.max_req_size = uvc->video.ep->maxpacket
|
||||
* max_t(unsigned int, uvc->video.ep->maxburst, 1)
|
||||
* (uvc->video.ep->mult);
|
||||
|
||||
memset(&v4l2_event, 0, sizeof(v4l2_event));
|
||||
v4l2_event.type = UVC_EVENT_STREAMON;
|
||||
v4l2_event_queue(&uvc->vdev, &v4l2_event);
|
||||
|
||||
@@ -107,7 +107,7 @@ struct uvc_video {
|
||||
unsigned int width;
|
||||
unsigned int height;
|
||||
unsigned int imagesize;
|
||||
unsigned int interval;
|
||||
unsigned int interval; /* in 100ns units */
|
||||
struct mutex mutex; /* protects frame parameters */
|
||||
|
||||
unsigned int uvc_num_requests;
|
||||
@@ -117,6 +117,7 @@ struct uvc_video {
|
||||
/* Requests */
|
||||
bool is_enabled; /* tracks whether video stream is enabled */
|
||||
unsigned int req_size;
|
||||
unsigned int max_req_size;
|
||||
struct list_head ureqs; /* all uvc_requests allocated by uvc_video */
|
||||
|
||||
/* USB requests that the video pump thread can encode into */
|
||||
|
||||
@@ -86,10 +86,17 @@ static int uvc_buffer_prepare(struct vb2_buffer *vb)
|
||||
buf->bytesused = 0;
|
||||
} else {
|
||||
buf->bytesused = vb2_get_plane_payload(vb, 0);
|
||||
buf->req_payload_size =
|
||||
DIV_ROUND_UP(buf->bytesused +
|
||||
(video->reqs_per_frame * UVCG_REQUEST_HEADER_LEN),
|
||||
video->reqs_per_frame);
|
||||
|
||||
if (video->reqs_per_frame != 0) {
|
||||
buf->req_payload_size =
|
||||
DIV_ROUND_UP(buf->bytesused +
|
||||
(video->reqs_per_frame * UVCG_REQUEST_HEADER_LEN),
|
||||
video->reqs_per_frame);
|
||||
if (buf->req_payload_size > video->req_size)
|
||||
buf->req_payload_size = video->req_size;
|
||||
} else {
|
||||
buf->req_payload_size = video->max_req_size;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -175,7 +182,15 @@ int uvcg_alloc_buffers(struct uvc_video_queue *queue,
|
||||
{
|
||||
int ret;
|
||||
|
||||
retry:
|
||||
ret = vb2_reqbufs(&queue->queue, rb);
|
||||
if (ret < 0 && queue->use_sg) {
|
||||
uvc_trace(UVC_TRACE_IOCTL,
|
||||
"failed to alloc buffer with sg enabled, try non-sg mode\n");
|
||||
queue->use_sg = 0;
|
||||
queue->queue.mem_ops = &vb2_vmalloc_memops;
|
||||
goto retry;
|
||||
}
|
||||
|
||||
return ret ? ret : rb->count;
|
||||
}
|
||||
|
||||
@@ -499,13 +499,11 @@ uvc_video_prep_requests(struct uvc_video *video)
|
||||
{
|
||||
struct uvc_device *uvc = container_of(video, struct uvc_device, video);
|
||||
struct usb_composite_dev *cdev = uvc->func.config->cdev;
|
||||
unsigned int interval_duration = video->ep->desc->bInterval * 1250;
|
||||
unsigned int interval_duration;
|
||||
unsigned int max_req_size, req_size, header_size;
|
||||
unsigned int nreq;
|
||||
|
||||
max_req_size = video->ep->maxpacket
|
||||
* max_t(unsigned int, video->ep->maxburst, 1)
|
||||
* (video->ep->mult);
|
||||
max_req_size = video->max_req_size;
|
||||
|
||||
if (!usb_endpoint_xfer_isoc(video->ep->desc)) {
|
||||
video->req_size = max_req_size;
|
||||
@@ -515,8 +513,11 @@ uvc_video_prep_requests(struct uvc_video *video)
|
||||
return;
|
||||
}
|
||||
|
||||
interval_duration = 2 << (video->ep->desc->bInterval - 1);
|
||||
if (cdev->gadget->speed < USB_SPEED_HIGH)
|
||||
interval_duration = video->ep->desc->bInterval * 10000;
|
||||
interval_duration *= 10000;
|
||||
else
|
||||
interval_duration *= 1250;
|
||||
|
||||
nreq = DIV_ROUND_UP(video->interval, interval_duration);
|
||||
|
||||
@@ -837,7 +838,6 @@ int uvcg_video_init(struct uvc_video *video, struct uvc_device *uvc)
|
||||
video->interval = 666666;
|
||||
|
||||
/* Initialize the video buffers queue. */
|
||||
uvcg_queue_init(&video->queue, uvc->v4l2_dev.dev->parent,
|
||||
return uvcg_queue_init(&video->queue, uvc->v4l2_dev.dev->parent,
|
||||
V4L2_BUF_TYPE_VIDEO_OUTPUT, &video->mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -392,3 +392,4 @@ MODULE_DESCRIPTION(DRIVER_DESC);
|
||||
MODULE_AUTHOR("Hauke Mehrtens");
|
||||
MODULE_AUTHOR("Alan Stern");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_SOFTDEP("pre: ehci_platform");
|
||||
|
||||
@@ -211,3 +211,4 @@ static struct platform_driver uhci_platform_driver = {
|
||||
.of_match_table = platform_uhci_ids,
|
||||
},
|
||||
};
|
||||
MODULE_SOFTDEP("pre: ehci_platform");
|
||||
|
||||
@@ -210,7 +210,6 @@ xhci_sideband_remove_endpoint(struct xhci_sideband *sb,
|
||||
return -ENODEV;
|
||||
|
||||
__xhci_sideband_remove_endpoint(sb, ep);
|
||||
xhci_initialize_ring_info(ep->ring);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1563,7 +1563,7 @@ static int tegra_xusb_setup_wakeup(struct platform_device *pdev, struct tegra_xu
|
||||
for (i = 0; i < tegra->soc->max_num_wakes; i++) {
|
||||
struct irq_data *data;
|
||||
|
||||
tegra->wake_irqs[i] = platform_get_irq(pdev, i + WAKE_IRQ_START_INDEX);
|
||||
tegra->wake_irqs[i] = platform_get_irq_optional(pdev, i + WAKE_IRQ_START_INDEX);
|
||||
if (tegra->wake_irqs[i] < 0)
|
||||
break;
|
||||
|
||||
|
||||
@@ -2898,16 +2898,25 @@ int xhci_stop_endpoint_sync(struct xhci_hcd *xhci, struct xhci_virt_ep *ep, int
|
||||
gfp_t gfp_flags)
|
||||
{
|
||||
struct xhci_command *command;
|
||||
struct xhci_ep_ctx *ep_ctx;
|
||||
unsigned long flags;
|
||||
int ret;
|
||||
int ret = -ENODEV;
|
||||
|
||||
command = xhci_alloc_command(xhci, true, gfp_flags);
|
||||
if (!command)
|
||||
return -ENOMEM;
|
||||
|
||||
spin_lock_irqsave(&xhci->lock, flags);
|
||||
ret = xhci_queue_stop_endpoint(xhci, command, ep->vdev->slot_id,
|
||||
ep->ep_index, suspend);
|
||||
|
||||
/* make sure endpoint exists and is running before stopping it */
|
||||
if (ep->ring) {
|
||||
ep_ctx = xhci_get_ep_ctx(xhci, ep->vdev->out_ctx, ep->ep_index);
|
||||
if (GET_EP_CTX_STATE(ep_ctx) == EP_STATE_RUNNING)
|
||||
ret = xhci_queue_stop_endpoint(xhci, command,
|
||||
ep->vdev->slot_id,
|
||||
ep->ep_index, suspend);
|
||||
}
|
||||
|
||||
if (ret < 0) {
|
||||
spin_unlock_irqrestore(&xhci->lock, flags);
|
||||
goto out;
|
||||
|
||||
@@ -70,7 +70,6 @@ MODULE_DEVICE_TABLE(usb, combined_id_table);
|
||||
#define F81232_REGISTER_REQUEST 0xa0
|
||||
#define F81232_GET_REGISTER 0xc0
|
||||
#define F81232_SET_REGISTER 0x40
|
||||
#define F81534A_ACCESS_REG_RETRY 2
|
||||
|
||||
#define SERIAL_BASE_ADDRESS 0x0120
|
||||
#define RECEIVE_BUFFER_REGISTER (0x00 + SERIAL_BASE_ADDRESS)
|
||||
@@ -824,36 +823,31 @@ static void f81232_lsr_worker(struct work_struct *work)
|
||||
static int f81534a_ctrl_set_register(struct usb_interface *intf, u16 reg,
|
||||
u16 size, void *val)
|
||||
{
|
||||
struct usb_device *dev = interface_to_usbdev(intf);
|
||||
int retry = F81534A_ACCESS_REG_RETRY;
|
||||
int status;
|
||||
return usb_control_msg_send(interface_to_usbdev(intf),
|
||||
0,
|
||||
F81232_REGISTER_REQUEST,
|
||||
F81232_SET_REGISTER,
|
||||
reg,
|
||||
0,
|
||||
val,
|
||||
size,
|
||||
USB_CTRL_SET_TIMEOUT,
|
||||
GFP_KERNEL);
|
||||
}
|
||||
|
||||
while (retry--) {
|
||||
status = usb_control_msg_send(dev,
|
||||
0,
|
||||
F81232_REGISTER_REQUEST,
|
||||
F81232_SET_REGISTER,
|
||||
reg,
|
||||
0,
|
||||
val,
|
||||
size,
|
||||
USB_CTRL_SET_TIMEOUT,
|
||||
GFP_KERNEL);
|
||||
if (status) {
|
||||
status = usb_translate_errors(status);
|
||||
if (status == -EIO)
|
||||
continue;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if (status) {
|
||||
dev_err(&intf->dev, "failed to set register 0x%x: %d\n",
|
||||
reg, status);
|
||||
}
|
||||
|
||||
return status;
|
||||
static int f81534a_ctrl_get_register(struct usb_interface *intf, u16 reg,
|
||||
u16 size, void *val)
|
||||
{
|
||||
return usb_control_msg_recv(interface_to_usbdev(intf),
|
||||
0,
|
||||
F81232_REGISTER_REQUEST,
|
||||
F81232_GET_REGISTER,
|
||||
reg,
|
||||
0,
|
||||
val,
|
||||
size,
|
||||
USB_CTRL_GET_TIMEOUT,
|
||||
GFP_KERNEL);
|
||||
}
|
||||
|
||||
static int f81534a_ctrl_enable_all_ports(struct usb_interface *intf, bool en)
|
||||
@@ -869,6 +863,29 @@ static int f81534a_ctrl_enable_all_ports(struct usb_interface *intf, bool en)
|
||||
* bit 0~11 : Serial port enable bit.
|
||||
*/
|
||||
if (en) {
|
||||
/*
|
||||
* The Fintek F81532A/534A/535/536 family relies on the
|
||||
* F81534A_CTRL_CMD_ENABLE_PORT (116h) register during
|
||||
* initialization to both determine serial port status and
|
||||
* control port creation.
|
||||
*
|
||||
* If the driver experiences fast load/unload cycles, the
|
||||
* device state may becomes unstable, resulting in the
|
||||
* incomplete generation of serial ports.
|
||||
*
|
||||
* Performing a dummy read operation on the register prior
|
||||
* to the initial write command resolves the issue.
|
||||
*
|
||||
* This clears the device's stale internal state. Subsequent
|
||||
* write operations will correctly generate all serial ports.
|
||||
*/
|
||||
status = f81534a_ctrl_get_register(intf,
|
||||
F81534A_CTRL_CMD_ENABLE_PORT,
|
||||
sizeof(enable),
|
||||
enable);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
enable[0] = 0xff;
|
||||
enable[1] = 0x8f;
|
||||
}
|
||||
|
||||
@@ -848,6 +848,7 @@ static const struct usb_device_id id_table_combined[] = {
|
||||
{ USB_DEVICE_INTERFACE_NUMBER(FTDI_VID, LMI_LM3S_DEVEL_BOARD_PID, 1) },
|
||||
{ USB_DEVICE_INTERFACE_NUMBER(FTDI_VID, LMI_LM3S_EVAL_BOARD_PID, 1) },
|
||||
{ USB_DEVICE_INTERFACE_NUMBER(FTDI_VID, LMI_LM3S_ICDI_BOARD_PID, 1) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_AXE027_PID) },
|
||||
{ USB_DEVICE_INTERFACE_NUMBER(FTDI_VID, FTDI_TURTELIZER_PID, 1) },
|
||||
{ USB_DEVICE(RATOC_VENDOR_ID, RATOC_PRODUCT_ID_USB60F) },
|
||||
{ USB_DEVICE(RATOC_VENDOR_ID, RATOC_PRODUCT_ID_SCU18) },
|
||||
|
||||
@@ -96,6 +96,8 @@
|
||||
#define LMI_LM3S_EVAL_BOARD_PID 0xbcd9
|
||||
#define LMI_LM3S_ICDI_BOARD_PID 0xbcda
|
||||
|
||||
#define FTDI_AXE027_PID 0xBD90 /* PICAXE AXE027 USB download cable */
|
||||
|
||||
#define FTDI_TURTELIZER_PID 0xBDC8 /* JTAG/RS-232 adapter by egnite GmbH */
|
||||
|
||||
/* OpenDCC (www.opendcc.de) product id */
|
||||
|
||||
@@ -1505,6 +1505,7 @@ static const struct usb_device_id option_ids[] = {
|
||||
{ USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1231, 0xff), /* Telit LE910Cx (RNDIS) */
|
||||
.driver_info = NCTRL(2) | RSVD(3) },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(TELIT_VENDOR_ID, 0x1250, 0xff, 0x00, 0x00) }, /* Telit LE910Cx (rmnet) */
|
||||
{ USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1252, 0xff) }, /* Telit LE910Cx (MBIM) */
|
||||
{ USB_DEVICE(TELIT_VENDOR_ID, 0x1260),
|
||||
.driver_info = NCTRL(0) | RSVD(1) | RSVD(2) },
|
||||
{ USB_DEVICE(TELIT_VENDOR_ID, 0x1261),
|
||||
|
||||
@@ -7890,7 +7890,7 @@ struct tcpm_port *tcpm_register_port(struct device *dev, struct tcpc_dev *tcpc)
|
||||
port->partner_desc.identity = &port->partner_ident;
|
||||
|
||||
port->role_sw = fwnode_usb_role_switch_get(tcpc->fwnode);
|
||||
if (!port->role_sw)
|
||||
if (IS_ERR_OR_NULL(port->role_sw))
|
||||
port->role_sw = usb_role_switch_get(port->dev);
|
||||
if (IS_ERR(port->role_sw)) {
|
||||
err = PTR_ERR(port->role_sw);
|
||||
|
||||
@@ -75,4 +75,7 @@
|
||||
/* short SET_ADDRESS request timeout */
|
||||
#define USB_QUIRK_SHORT_SET_ADDRESS_REQ_TIMEOUT BIT(16)
|
||||
|
||||
/* skip BOS descriptor request */
|
||||
#define USB_QUIRK_NO_BOS BIT(17)
|
||||
|
||||
#endif /* __LINUX_USB_QUIRKS_H */
|
||||
|
||||
Reference in New Issue
Block a user