mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git
synced 2025-01-17 05:45:20 +00:00
USB driver fixes for 6.13-rc3
Here are some small USB driver fixes for some reported issues. Included in here are: - typec driver bugfixes - u_serial gadget driver bugfix for much reported and discussed issue - dwc2 bugfixes - midi gadget driver bugfix - ehci-hcd driver bugfix - other small bugfixes All of these have been in linux-next for over a week with no reported issues. Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> -----BEGIN PGP SIGNATURE----- iG0EABECAC0WIQT0tgzFv3jCIUoxPcsxR9QN2y37KQUCZ12Wwg8cZ3JlZ0Brcm9h aC5jb20ACgkQMUfUDdst+ymbWgCeKUCeGFlUanDHY1nHq72FSMiHpcUAoIvzBTx1 yUEhvtuYYZ/NBzfKI+8h =WeQD -----END PGP SIGNATURE----- Merge tag 'usb-6.13-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb Pull USB driver fixes from Greg KH: "Here are some small USB driver fixes for some reported issues. Included in here are: - typec driver bugfixes - u_serial gadget driver bugfix for much reported and discussed issue - dwc2 bugfixes - midi gadget driver bugfix - ehci-hcd driver bugfix - other small bugfixes All of these have been in linux-next for over a week with no reported issues" * tag 'usb-6.13-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb: usb: typec: ucsi: Fix connector status writing past buffer size usb: typec: ucsi: Fix completion notifications usb: dwc2: Fix HCD port connection race usb: dwc2: hcd: Fix GetPortStatus & SetPortFeature usb: dwc2: Fix HCD resume usb: gadget: u_serial: Fix the issue that gs_start_io crashed due to accessing null pointer usb: misc: onboard_usb_dev: skip suspend/resume sequence for USB5744 SMBus support usb: dwc3: xilinx: make sure pipe clock is deselected in usb2 only mode usb: core: hcd: only check primary hcd skip_phy_initialization usb: gadget: midi2: Fix interpretation of is_midi1 bits usb: dwc3: imx8mp: fix software node kernel dump usb: typec: anx7411: fix OF node reference leaks in anx7411_typec_switch_probe() usb: typec: anx7411: fix fwnode_handle reference leak usb: host: max3421-hcd: Correctly abort a USB request. dt-bindings: phy: imx8mq-usb: correct reference to usb-switch.yaml usb: ehci-hcd: fix call balance of clocks handling routines
This commit is contained in:
commit
a0e3919a2d
@ -113,11 +113,8 @@ allOf:
|
|||||||
maxItems: 1
|
maxItems: 1
|
||||||
|
|
||||||
- if:
|
- if:
|
||||||
properties:
|
required:
|
||||||
compatible:
|
- orientation-switch
|
||||||
contains:
|
|
||||||
enum:
|
|
||||||
- fsl,imx95-usb-phy
|
|
||||||
then:
|
then:
|
||||||
$ref: /schemas/usb/usb-switch.yaml#
|
$ref: /schemas/usb/usb-switch.yaml#
|
||||||
|
|
||||||
|
@ -2794,8 +2794,14 @@ int usb_add_hcd(struct usb_hcd *hcd,
|
|||||||
int retval;
|
int retval;
|
||||||
struct usb_device *rhdev;
|
struct usb_device *rhdev;
|
||||||
struct usb_hcd *shared_hcd;
|
struct usb_hcd *shared_hcd;
|
||||||
|
int skip_phy_initialization;
|
||||||
|
|
||||||
if (!hcd->skip_phy_initialization) {
|
if (usb_hcd_is_primary_hcd(hcd))
|
||||||
|
skip_phy_initialization = hcd->skip_phy_initialization;
|
||||||
|
else
|
||||||
|
skip_phy_initialization = hcd->primary_hcd->skip_phy_initialization;
|
||||||
|
|
||||||
|
if (!skip_phy_initialization) {
|
||||||
if (usb_hcd_is_primary_hcd(hcd)) {
|
if (usb_hcd_is_primary_hcd(hcd)) {
|
||||||
hcd->phy_roothub = usb_phy_roothub_alloc(hcd->self.sysdev);
|
hcd->phy_roothub = usb_phy_roothub_alloc(hcd->self.sysdev);
|
||||||
if (IS_ERR(hcd->phy_roothub))
|
if (IS_ERR(hcd->phy_roothub))
|
||||||
|
@ -3546,11 +3546,9 @@ static int dwc2_hcd_hub_control(struct dwc2_hsotg *hsotg, u16 typereq,
|
|||||||
port_status |= USB_PORT_STAT_C_OVERCURRENT << 16;
|
port_status |= USB_PORT_STAT_C_OVERCURRENT << 16;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!hsotg->flags.b.port_connect_status) {
|
if (dwc2_is_device_mode(hsotg)) {
|
||||||
/*
|
/*
|
||||||
* The port is disconnected, which means the core is
|
* Just return 0's for the remainder of the port status
|
||||||
* either in device mode or it soon will be. Just
|
|
||||||
* return 0's for the remainder of the port status
|
|
||||||
* since the port register can't be read if the core
|
* since the port register can't be read if the core
|
||||||
* is in device mode.
|
* is in device mode.
|
||||||
*/
|
*/
|
||||||
@ -3620,13 +3618,11 @@ static int dwc2_hcd_hub_control(struct dwc2_hsotg *hsotg, u16 typereq,
|
|||||||
if (wvalue != USB_PORT_FEAT_TEST && (!windex || windex > 1))
|
if (wvalue != USB_PORT_FEAT_TEST && (!windex || windex > 1))
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
if (!hsotg->flags.b.port_connect_status) {
|
if (dwc2_is_device_mode(hsotg)) {
|
||||||
/*
|
/*
|
||||||
* The port is disconnected, which means the core is
|
* Just return 0's for the remainder of the port status
|
||||||
* either in device mode or it soon will be. Just
|
* since the port register can't be read if the core
|
||||||
* return without doing anything since the port
|
* is in device mode.
|
||||||
* register can't be written if the core is in device
|
|
||||||
* mode.
|
|
||||||
*/
|
*/
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -4349,7 +4345,7 @@ static int _dwc2_hcd_suspend(struct usb_hcd *hcd)
|
|||||||
if (hsotg->bus_suspended)
|
if (hsotg->bus_suspended)
|
||||||
goto skip_power_saving;
|
goto skip_power_saving;
|
||||||
|
|
||||||
if (hsotg->flags.b.port_connect_status == 0)
|
if (!(dwc2_read_hprt0(hsotg) & HPRT0_CONNSTS))
|
||||||
goto skip_power_saving;
|
goto skip_power_saving;
|
||||||
|
|
||||||
switch (hsotg->params.power_down) {
|
switch (hsotg->params.power_down) {
|
||||||
@ -4431,6 +4427,7 @@ static int _dwc2_hcd_resume(struct usb_hcd *hcd)
|
|||||||
* Power Down mode.
|
* Power Down mode.
|
||||||
*/
|
*/
|
||||||
if (hprt0 & HPRT0_CONNSTS) {
|
if (hprt0 & HPRT0_CONNSTS) {
|
||||||
|
set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
|
||||||
hsotg->lx_state = DWC2_L0;
|
hsotg->lx_state = DWC2_L0;
|
||||||
goto unlock;
|
goto unlock;
|
||||||
}
|
}
|
||||||
|
@ -129,6 +129,16 @@ static void dwc3_imx8mp_wakeup_disable(struct dwc3_imx8mp *dwc3_imx)
|
|||||||
writel(val, dwc3_imx->hsio_blk_base + USB_WAKEUP_CTRL);
|
writel(val, dwc3_imx->hsio_blk_base + USB_WAKEUP_CTRL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const struct property_entry dwc3_imx8mp_properties[] = {
|
||||||
|
PROPERTY_ENTRY_BOOL("xhci-missing-cas-quirk"),
|
||||||
|
PROPERTY_ENTRY_BOOL("xhci-skip-phy-init-quirk"),
|
||||||
|
{},
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct software_node dwc3_imx8mp_swnode = {
|
||||||
|
.properties = dwc3_imx8mp_properties,
|
||||||
|
};
|
||||||
|
|
||||||
static irqreturn_t dwc3_imx8mp_interrupt(int irq, void *_dwc3_imx)
|
static irqreturn_t dwc3_imx8mp_interrupt(int irq, void *_dwc3_imx)
|
||||||
{
|
{
|
||||||
struct dwc3_imx8mp *dwc3_imx = _dwc3_imx;
|
struct dwc3_imx8mp *dwc3_imx = _dwc3_imx;
|
||||||
@ -148,17 +158,6 @@ static irqreturn_t dwc3_imx8mp_interrupt(int irq, void *_dwc3_imx)
|
|||||||
return IRQ_HANDLED;
|
return IRQ_HANDLED;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int dwc3_imx8mp_set_software_node(struct device *dev)
|
|
||||||
{
|
|
||||||
struct property_entry props[3] = { 0 };
|
|
||||||
int prop_idx = 0;
|
|
||||||
|
|
||||||
props[prop_idx++] = PROPERTY_ENTRY_BOOL("xhci-missing-cas-quirk");
|
|
||||||
props[prop_idx++] = PROPERTY_ENTRY_BOOL("xhci-skip-phy-init-quirk");
|
|
||||||
|
|
||||||
return device_create_managed_software_node(dev, props, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int dwc3_imx8mp_probe(struct platform_device *pdev)
|
static int dwc3_imx8mp_probe(struct platform_device *pdev)
|
||||||
{
|
{
|
||||||
struct device *dev = &pdev->dev;
|
struct device *dev = &pdev->dev;
|
||||||
@ -221,17 +220,17 @@ static int dwc3_imx8mp_probe(struct platform_device *pdev)
|
|||||||
if (err < 0)
|
if (err < 0)
|
||||||
goto disable_rpm;
|
goto disable_rpm;
|
||||||
|
|
||||||
err = dwc3_imx8mp_set_software_node(dev);
|
err = device_add_software_node(dev, &dwc3_imx8mp_swnode);
|
||||||
if (err) {
|
if (err) {
|
||||||
err = -ENODEV;
|
err = -ENODEV;
|
||||||
dev_err(dev, "failed to create software node\n");
|
dev_err(dev, "failed to add software node\n");
|
||||||
goto disable_rpm;
|
goto disable_rpm;
|
||||||
}
|
}
|
||||||
|
|
||||||
err = of_platform_populate(node, NULL, NULL, dev);
|
err = of_platform_populate(node, NULL, NULL, dev);
|
||||||
if (err) {
|
if (err) {
|
||||||
dev_err(&pdev->dev, "failed to create dwc3 core\n");
|
dev_err(&pdev->dev, "failed to create dwc3 core\n");
|
||||||
goto disable_rpm;
|
goto remove_swnode;
|
||||||
}
|
}
|
||||||
|
|
||||||
dwc3_imx->dwc3 = of_find_device_by_node(dwc3_np);
|
dwc3_imx->dwc3 = of_find_device_by_node(dwc3_np);
|
||||||
@ -255,6 +254,8 @@ static int dwc3_imx8mp_probe(struct platform_device *pdev)
|
|||||||
|
|
||||||
depopulate:
|
depopulate:
|
||||||
of_platform_depopulate(dev);
|
of_platform_depopulate(dev);
|
||||||
|
remove_swnode:
|
||||||
|
device_remove_software_node(dev);
|
||||||
disable_rpm:
|
disable_rpm:
|
||||||
pm_runtime_disable(dev);
|
pm_runtime_disable(dev);
|
||||||
pm_runtime_put_noidle(dev);
|
pm_runtime_put_noidle(dev);
|
||||||
@ -268,6 +269,7 @@ static void dwc3_imx8mp_remove(struct platform_device *pdev)
|
|||||||
|
|
||||||
pm_runtime_get_sync(dev);
|
pm_runtime_get_sync(dev);
|
||||||
of_platform_depopulate(dev);
|
of_platform_depopulate(dev);
|
||||||
|
device_remove_software_node(dev);
|
||||||
|
|
||||||
pm_runtime_disable(dev);
|
pm_runtime_disable(dev);
|
||||||
pm_runtime_put_noidle(dev);
|
pm_runtime_put_noidle(dev);
|
||||||
|
@ -121,8 +121,11 @@ static int dwc3_xlnx_init_zynqmp(struct dwc3_xlnx *priv_data)
|
|||||||
* in use but the usb3-phy entry is missing from the device tree.
|
* in use but the usb3-phy entry is missing from the device tree.
|
||||||
* Therefore, skip these operations in this case.
|
* Therefore, skip these operations in this case.
|
||||||
*/
|
*/
|
||||||
if (!priv_data->usb3_phy)
|
if (!priv_data->usb3_phy) {
|
||||||
|
/* Deselect the PIPE Clock Select bit in FPD PIPE Clock register */
|
||||||
|
writel(PIPE_CLK_DESELECT, priv_data->regs + XLNX_USB_FPD_PIPE_CLK);
|
||||||
goto skip_usb3_phy;
|
goto skip_usb3_phy;
|
||||||
|
}
|
||||||
|
|
||||||
crst = devm_reset_control_get_exclusive(dev, "usb_crst");
|
crst = devm_reset_control_get_exclusive(dev, "usb_crst");
|
||||||
if (IS_ERR(crst)) {
|
if (IS_ERR(crst)) {
|
||||||
|
@ -1591,7 +1591,11 @@ static int f_midi2_create_card(struct f_midi2 *midi2)
|
|||||||
fb->info.midi_ci_version = b->midi_ci_version;
|
fb->info.midi_ci_version = b->midi_ci_version;
|
||||||
fb->info.ui_hint = reverse_dir(b->ui_hint);
|
fb->info.ui_hint = reverse_dir(b->ui_hint);
|
||||||
fb->info.sysex8_streams = b->sysex8_streams;
|
fb->info.sysex8_streams = b->sysex8_streams;
|
||||||
|
if (b->is_midi1 < 2)
|
||||||
fb->info.flags |= b->is_midi1;
|
fb->info.flags |= b->is_midi1;
|
||||||
|
else
|
||||||
|
fb->info.flags |= SNDRV_UMP_BLOCK_IS_MIDI1 |
|
||||||
|
SNDRV_UMP_BLOCK_IS_LOWSPEED;
|
||||||
strscpy(fb->info.name, ump_fb_name(b),
|
strscpy(fb->info.name, ump_fb_name(b),
|
||||||
sizeof(fb->info.name));
|
sizeof(fb->info.name));
|
||||||
}
|
}
|
||||||
|
@ -579,9 +579,12 @@ static int gs_start_io(struct gs_port *port)
|
|||||||
* we didn't in gs_start_tx() */
|
* we didn't in gs_start_tx() */
|
||||||
tty_wakeup(port->port.tty);
|
tty_wakeup(port->port.tty);
|
||||||
} else {
|
} else {
|
||||||
|
/* Free reqs only if we are still connected */
|
||||||
|
if (port->port_usb) {
|
||||||
gs_free_requests(ep, head, &port->read_allocated);
|
gs_free_requests(ep, head, &port->read_allocated);
|
||||||
gs_free_requests(port->port_usb->in, &port->write_pool,
|
gs_free_requests(port->port_usb->in, &port->write_pool,
|
||||||
&port->write_allocated);
|
&port->write_allocated);
|
||||||
|
}
|
||||||
status = -EIO;
|
status = -EIO;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -119,8 +119,12 @@ static int ehci_hcd_sh_probe(struct platform_device *pdev)
|
|||||||
if (IS_ERR(priv->iclk))
|
if (IS_ERR(priv->iclk))
|
||||||
priv->iclk = NULL;
|
priv->iclk = NULL;
|
||||||
|
|
||||||
clk_enable(priv->fclk);
|
ret = clk_enable(priv->fclk);
|
||||||
clk_enable(priv->iclk);
|
if (ret)
|
||||||
|
goto fail_request_resource;
|
||||||
|
ret = clk_enable(priv->iclk);
|
||||||
|
if (ret)
|
||||||
|
goto fail_iclk;
|
||||||
|
|
||||||
ret = usb_add_hcd(hcd, irq, IRQF_SHARED);
|
ret = usb_add_hcd(hcd, irq, IRQF_SHARED);
|
||||||
if (ret != 0) {
|
if (ret != 0) {
|
||||||
@ -136,6 +140,7 @@ static int ehci_hcd_sh_probe(struct platform_device *pdev)
|
|||||||
|
|
||||||
fail_add_hcd:
|
fail_add_hcd:
|
||||||
clk_disable(priv->iclk);
|
clk_disable(priv->iclk);
|
||||||
|
fail_iclk:
|
||||||
clk_disable(priv->fclk);
|
clk_disable(priv->fclk);
|
||||||
|
|
||||||
fail_request_resource:
|
fail_request_resource:
|
||||||
|
@ -779,6 +779,11 @@ max3421_check_unlink(struct usb_hcd *hcd)
|
|||||||
retval = 1;
|
retval = 1;
|
||||||
dev_dbg(&spi->dev, "%s: URB %p unlinked=%d",
|
dev_dbg(&spi->dev, "%s: URB %p unlinked=%d",
|
||||||
__func__, urb, urb->unlinked);
|
__func__, urb, urb->unlinked);
|
||||||
|
if (urb == max3421_hcd->curr_urb) {
|
||||||
|
max3421_hcd->urb_done = 1;
|
||||||
|
max3421_hcd->hien &= ~(BIT(MAX3421_HI_HXFRDN_BIT) |
|
||||||
|
BIT(MAX3421_HI_RCVDAV_BIT));
|
||||||
|
} else {
|
||||||
usb_hcd_unlink_urb_from_ep(hcd, urb);
|
usb_hcd_unlink_urb_from_ep(hcd, urb);
|
||||||
spin_unlock_irqrestore(&max3421_hcd->lock,
|
spin_unlock_irqrestore(&max3421_hcd->lock,
|
||||||
flags);
|
flags);
|
||||||
@ -787,6 +792,7 @@ max3421_check_unlink(struct usb_hcd *hcd)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
spin_unlock_irqrestore(&max3421_hcd->lock, flags);
|
spin_unlock_irqrestore(&max3421_hcd->lock, flags);
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
@ -407,8 +407,10 @@ static int onboard_dev_probe(struct platform_device *pdev)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (of_device_is_compatible(pdev->dev.of_node, "usb424,2744") ||
|
if (of_device_is_compatible(pdev->dev.of_node, "usb424,2744") ||
|
||||||
of_device_is_compatible(pdev->dev.of_node, "usb424,5744"))
|
of_device_is_compatible(pdev->dev.of_node, "usb424,5744")) {
|
||||||
err = onboard_dev_5744_i2c_init(client);
|
err = onboard_dev_5744_i2c_init(client);
|
||||||
|
onboard_dev->always_powered_in_suspend = true;
|
||||||
|
}
|
||||||
|
|
||||||
put_device(&client->dev);
|
put_device(&client->dev);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
|
@ -290,6 +290,8 @@ struct anx7411_data {
|
|||||||
struct power_supply *psy;
|
struct power_supply *psy;
|
||||||
struct power_supply_desc psy_desc;
|
struct power_supply_desc psy_desc;
|
||||||
struct device *dev;
|
struct device *dev;
|
||||||
|
struct fwnode_handle *switch_node;
|
||||||
|
struct fwnode_handle *mux_node;
|
||||||
};
|
};
|
||||||
|
|
||||||
static u8 snk_identity[] = {
|
static u8 snk_identity[] = {
|
||||||
@ -1021,6 +1023,16 @@ static void anx7411_port_unregister_altmodes(struct typec_altmode **adev)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void anx7411_port_unregister(struct typec_params *typecp)
|
||||||
|
{
|
||||||
|
fwnode_handle_put(typecp->caps.fwnode);
|
||||||
|
anx7411_port_unregister_altmodes(typecp->port_amode);
|
||||||
|
if (typecp->port)
|
||||||
|
typec_unregister_port(typecp->port);
|
||||||
|
if (typecp->role_sw)
|
||||||
|
usb_role_switch_put(typecp->role_sw);
|
||||||
|
}
|
||||||
|
|
||||||
static int anx7411_usb_mux_set(struct typec_mux_dev *mux,
|
static int anx7411_usb_mux_set(struct typec_mux_dev *mux,
|
||||||
struct typec_mux_state *state)
|
struct typec_mux_state *state)
|
||||||
{
|
{
|
||||||
@ -1089,6 +1101,7 @@ static void anx7411_unregister_mux(struct anx7411_data *ctx)
|
|||||||
if (ctx->typec.typec_mux) {
|
if (ctx->typec.typec_mux) {
|
||||||
typec_mux_unregister(ctx->typec.typec_mux);
|
typec_mux_unregister(ctx->typec.typec_mux);
|
||||||
ctx->typec.typec_mux = NULL;
|
ctx->typec.typec_mux = NULL;
|
||||||
|
fwnode_handle_put(ctx->mux_node);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1097,6 +1110,7 @@ static void anx7411_unregister_switch(struct anx7411_data *ctx)
|
|||||||
if (ctx->typec.typec_switch) {
|
if (ctx->typec.typec_switch) {
|
||||||
typec_switch_unregister(ctx->typec.typec_switch);
|
typec_switch_unregister(ctx->typec.typec_switch);
|
||||||
ctx->typec.typec_switch = NULL;
|
ctx->typec.typec_switch = NULL;
|
||||||
|
fwnode_handle_put(ctx->switch_node);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1104,28 +1118,29 @@ static int anx7411_typec_switch_probe(struct anx7411_data *ctx,
|
|||||||
struct device *dev)
|
struct device *dev)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
struct device_node *node;
|
|
||||||
|
|
||||||
node = of_get_child_by_name(dev->of_node, "orientation_switch");
|
ctx->switch_node = device_get_named_child_node(dev, "orientation_switch");
|
||||||
if (!node)
|
if (!ctx->switch_node)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
ret = anx7411_register_switch(ctx, dev, &node->fwnode);
|
ret = anx7411_register_switch(ctx, dev, ctx->switch_node);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
dev_err(dev, "failed register switch");
|
dev_err(dev, "failed register switch");
|
||||||
|
fwnode_handle_put(ctx->switch_node);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
node = of_get_child_by_name(dev->of_node, "mode_switch");
|
ctx->mux_node = device_get_named_child_node(dev, "mode_switch");
|
||||||
if (!node) {
|
if (!ctx->mux_node) {
|
||||||
dev_err(dev, "no typec mux exist");
|
dev_err(dev, "no typec mux exist");
|
||||||
ret = -ENODEV;
|
ret = -ENODEV;
|
||||||
goto unregister_switch;
|
goto unregister_switch;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = anx7411_register_mux(ctx, dev, &node->fwnode);
|
ret = anx7411_register_mux(ctx, dev, ctx->mux_node);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
dev_err(dev, "failed register mode switch");
|
dev_err(dev, "failed register mode switch");
|
||||||
|
fwnode_handle_put(ctx->mux_node);
|
||||||
ret = -ENODEV;
|
ret = -ENODEV;
|
||||||
goto unregister_switch;
|
goto unregister_switch;
|
||||||
}
|
}
|
||||||
@ -1154,34 +1169,34 @@ static int anx7411_typec_port_probe(struct anx7411_data *ctx,
|
|||||||
ret = fwnode_property_read_string(fwnode, "power-role", &buf);
|
ret = fwnode_property_read_string(fwnode, "power-role", &buf);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
dev_err(dev, "power-role not found: %d\n", ret);
|
dev_err(dev, "power-role not found: %d\n", ret);
|
||||||
return ret;
|
goto put_fwnode;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = typec_find_port_power_role(buf);
|
ret = typec_find_port_power_role(buf);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
goto put_fwnode;
|
||||||
cap->type = ret;
|
cap->type = ret;
|
||||||
|
|
||||||
ret = fwnode_property_read_string(fwnode, "data-role", &buf);
|
ret = fwnode_property_read_string(fwnode, "data-role", &buf);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
dev_err(dev, "data-role not found: %d\n", ret);
|
dev_err(dev, "data-role not found: %d\n", ret);
|
||||||
return ret;
|
goto put_fwnode;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = typec_find_port_data_role(buf);
|
ret = typec_find_port_data_role(buf);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
goto put_fwnode;
|
||||||
cap->data = ret;
|
cap->data = ret;
|
||||||
|
|
||||||
ret = fwnode_property_read_string(fwnode, "try-power-role", &buf);
|
ret = fwnode_property_read_string(fwnode, "try-power-role", &buf);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
dev_err(dev, "try-power-role not found: %d\n", ret);
|
dev_err(dev, "try-power-role not found: %d\n", ret);
|
||||||
return ret;
|
goto put_fwnode;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = typec_find_power_role(buf);
|
ret = typec_find_power_role(buf);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
goto put_fwnode;
|
||||||
cap->prefer_role = ret;
|
cap->prefer_role = ret;
|
||||||
|
|
||||||
/* Get source pdos */
|
/* Get source pdos */
|
||||||
@ -1193,7 +1208,7 @@ static int anx7411_typec_port_probe(struct anx7411_data *ctx,
|
|||||||
typecp->src_pdo_nr);
|
typecp->src_pdo_nr);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
dev_err(dev, "source cap validate failed: %d\n", ret);
|
dev_err(dev, "source cap validate failed: %d\n", ret);
|
||||||
return -EINVAL;
|
goto put_fwnode;
|
||||||
}
|
}
|
||||||
|
|
||||||
typecp->caps_flags |= HAS_SOURCE_CAP;
|
typecp->caps_flags |= HAS_SOURCE_CAP;
|
||||||
@ -1207,7 +1222,7 @@ static int anx7411_typec_port_probe(struct anx7411_data *ctx,
|
|||||||
typecp->sink_pdo_nr);
|
typecp->sink_pdo_nr);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
dev_err(dev, "sink cap validate failed: %d\n", ret);
|
dev_err(dev, "sink cap validate failed: %d\n", ret);
|
||||||
return -EINVAL;
|
goto put_fwnode;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < typecp->sink_pdo_nr; i++) {
|
for (i = 0; i < typecp->sink_pdo_nr; i++) {
|
||||||
@ -1251,13 +1266,21 @@ static int anx7411_typec_port_probe(struct anx7411_data *ctx,
|
|||||||
ret = PTR_ERR(ctx->typec.port);
|
ret = PTR_ERR(ctx->typec.port);
|
||||||
ctx->typec.port = NULL;
|
ctx->typec.port = NULL;
|
||||||
dev_err(dev, "Failed to register type c port %d\n", ret);
|
dev_err(dev, "Failed to register type c port %d\n", ret);
|
||||||
return ret;
|
goto put_usb_role_switch;
|
||||||
}
|
}
|
||||||
|
|
||||||
typec_port_register_altmodes(ctx->typec.port, NULL, ctx,
|
typec_port_register_altmodes(ctx->typec.port, NULL, ctx,
|
||||||
ctx->typec.port_amode,
|
ctx->typec.port_amode,
|
||||||
MAX_ALTMODE);
|
MAX_ALTMODE);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
put_usb_role_switch:
|
||||||
|
if (ctx->typec.role_sw)
|
||||||
|
usb_role_switch_put(ctx->typec.role_sw);
|
||||||
|
put_fwnode:
|
||||||
|
fwnode_handle_put(fwnode);
|
||||||
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int anx7411_typec_check_connection(struct anx7411_data *ctx)
|
static int anx7411_typec_check_connection(struct anx7411_data *ctx)
|
||||||
@ -1523,8 +1546,7 @@ free_wq:
|
|||||||
destroy_workqueue(plat->workqueue);
|
destroy_workqueue(plat->workqueue);
|
||||||
|
|
||||||
free_typec_port:
|
free_typec_port:
|
||||||
typec_unregister_port(plat->typec.port);
|
anx7411_port_unregister(&plat->typec);
|
||||||
anx7411_port_unregister_altmodes(plat->typec.port_amode);
|
|
||||||
|
|
||||||
free_typec_switch:
|
free_typec_switch:
|
||||||
anx7411_unregister_switch(plat);
|
anx7411_unregister_switch(plat);
|
||||||
@ -1548,17 +1570,11 @@ static void anx7411_i2c_remove(struct i2c_client *client)
|
|||||||
|
|
||||||
i2c_unregister_device(plat->spi_client);
|
i2c_unregister_device(plat->spi_client);
|
||||||
|
|
||||||
if (plat->typec.role_sw)
|
|
||||||
usb_role_switch_put(plat->typec.role_sw);
|
|
||||||
|
|
||||||
anx7411_unregister_mux(plat);
|
anx7411_unregister_mux(plat);
|
||||||
|
|
||||||
anx7411_unregister_switch(plat);
|
anx7411_unregister_switch(plat);
|
||||||
|
|
||||||
if (plat->typec.port)
|
anx7411_port_unregister(&plat->typec);
|
||||||
typec_unregister_port(plat->typec.port);
|
|
||||||
|
|
||||||
anx7411_port_unregister_altmodes(plat->typec.port_amode);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct i2c_device_id anx7411_id[] = {
|
static const struct i2c_device_id anx7411_id[] = {
|
||||||
|
@ -46,11 +46,11 @@ void ucsi_notify_common(struct ucsi *ucsi, u32 cci)
|
|||||||
ucsi_connector_change(ucsi, UCSI_CCI_CONNECTOR(cci));
|
ucsi_connector_change(ucsi, UCSI_CCI_CONNECTOR(cci));
|
||||||
|
|
||||||
if (cci & UCSI_CCI_ACK_COMPLETE &&
|
if (cci & UCSI_CCI_ACK_COMPLETE &&
|
||||||
test_bit(ACK_PENDING, &ucsi->flags))
|
test_and_clear_bit(ACK_PENDING, &ucsi->flags))
|
||||||
complete(&ucsi->complete);
|
complete(&ucsi->complete);
|
||||||
|
|
||||||
if (cci & UCSI_CCI_COMMAND_COMPLETE &&
|
if (cci & UCSI_CCI_COMMAND_COMPLETE &&
|
||||||
test_bit(COMMAND_PENDING, &ucsi->flags))
|
test_and_clear_bit(COMMAND_PENDING, &ucsi->flags))
|
||||||
complete(&ucsi->complete);
|
complete(&ucsi->complete);
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(ucsi_notify_common);
|
EXPORT_SYMBOL_GPL(ucsi_notify_common);
|
||||||
@ -65,6 +65,8 @@ int ucsi_sync_control_common(struct ucsi *ucsi, u64 command)
|
|||||||
else
|
else
|
||||||
set_bit(COMMAND_PENDING, &ucsi->flags);
|
set_bit(COMMAND_PENDING, &ucsi->flags);
|
||||||
|
|
||||||
|
reinit_completion(&ucsi->complete);
|
||||||
|
|
||||||
ret = ucsi->ops->async_control(ucsi, command);
|
ret = ucsi->ops->async_control(ucsi, command);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto out_clear_bit;
|
goto out_clear_bit;
|
||||||
@ -651,7 +653,8 @@ static void ucsi_unregister_altmodes(struct ucsi_connector *con, u8 recipient)
|
|||||||
static int ucsi_get_connector_status(struct ucsi_connector *con, bool conn_ack)
|
static int ucsi_get_connector_status(struct ucsi_connector *con, bool conn_ack)
|
||||||
{
|
{
|
||||||
u64 command = UCSI_GET_CONNECTOR_STATUS | UCSI_CONNECTOR_NUMBER(con->num);
|
u64 command = UCSI_GET_CONNECTOR_STATUS | UCSI_CONNECTOR_NUMBER(con->num);
|
||||||
size_t size = min(UCSI_GET_CONNECTOR_STATUS_SIZE, UCSI_MAX_DATA_LENGTH(con->ucsi));
|
size_t size = min(sizeof(con->status),
|
||||||
|
UCSI_MAX_DATA_LENGTH(con->ucsi));
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ret = ucsi_send_command_common(con->ucsi, command, &con->status, size, conn_ack);
|
ret = ucsi_send_command_common(con->ucsi, command, &con->status, size, conn_ack);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user