Hi,

Hauke Mehrtens <ha...@hauke-m.de> writes:
> From: Rafał Miłecki <zaj...@gmail.com>
>
> This fixes problem with controller seeing devices only in some small
> percentage of cold boots.
> This quirk is also added to the platform data so we can activate it
> when we register our platform driver.

it would've been nicer if you could add an erratum ID number for future
reference together with a more verbose discussion of the problem. You're
not describing what the problem is and that's important.

> Signed-off-by: Rafał Miłecki <zaj...@gmail.com>
> Signed-off-by: Hauke Mehrtens <ha...@hauke-m.de>
> ---
>  drivers/usb/host/xhci-plat.c     |  3 +++
>  drivers/usb/host/xhci.c          | 57 
> +++++++++++++++++++++++++++++++++++++---
>  drivers/usb/host/xhci.h          |  1 +
>  include/linux/usb/xhci_pdriver.h |  1 +
>  4 files changed, 59 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/usb/host/xhci-plat.c b/drivers/usb/host/xhci-plat.c
> index 4fb295b..7cd274b 100644
> --- a/drivers/usb/host/xhci-plat.c
> +++ b/drivers/usb/host/xhci-plat.c
> @@ -53,6 +53,9 @@ static void xhci_plat_quirks(struct device *dev, struct 
> xhci_hcd *xhci)
>       if ((node && of_property_read_bool(node, "usb3-lpm-capable")) ||
>                       (pdata && pdata->usb3_lpm_capable))
>               xhci->quirks |= XHCI_LPM_SUPPORT;
> +
> +     if (pdata && pdata->usb3_fake_doorbell)
> +             xhci->quirks |= XHCI_FAKE_DOORBELL;

whenever you add something via pdata, you _must_ make a similar DT change.

> diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
> index 643d312..d49be9b 100644
> --- a/drivers/usb/host/xhci.c
> +++ b/drivers/usb/host/xhci.c
> @@ -122,6 +122,39 @@ int xhci_halt(struct xhci_hcd *xhci)
>       return ret;
>  }
>  
> +static int xhci_fake_doorbell(struct xhci_hcd *xhci, int slot_id)
> +{
> +     u32 temp;
> +
> +     /* alloc a virt device for slot */
> +     if (!xhci_alloc_virt_device(xhci, slot_id, NULL, GFP_NOIO)) {
> +             xhci_warn(xhci, "Could not allocate xHCI USB device data 
> structures\n");
> +             return -ENOMEM;
> +     }
> +
> +     /* ring fake doorbell for slot_id ep 0 */
> +     xhci_ring_ep_doorbell(xhci, slot_id, 0, 0);
> +     usleep_range(1000, 1500);
> +
> +     /* read the status register to check if HSE is set or not? */
> +     temp = readl(&xhci->op_regs->status);
> +
> +     /* clear HSE if set */
> +     if (temp & STS_FATAL) {
> +             xhci_dbg(xhci, "HSE problem detected, status: 0x%x\n", temp);
> +             temp &= ~(0x1fff);
> +             temp |= STS_FATAL;
> +             writel(temp, &xhci->op_regs->status);
> +             usleep_range(1000, 1500);
> +             readl(&xhci->op_regs->status);
> +     }
> +
> +     /* Free virt device */
> +     xhci_free_virt_device(xhci, slot_id);
> +
> +     return 0;
> +}
> +
>  /*
>   * Set the run bit and wait for the host to be running.
>   */
> @@ -568,10 +601,25 @@ int xhci_init(struct usb_hcd *hcd)
>  
>  static int xhci_run_finished(struct xhci_hcd *xhci)
>  {
> -     if (xhci_start(xhci)) {
> -             xhci_halt(xhci);
> -             return -ENODEV;
> +     int err;
> +
> +     err = xhci_start(xhci);
> +     if (err) {
> +             err = -ENODEV;
> +             goto out_err;
> +     }

add a blank line here

> +     if (xhci->quirks & XHCI_FAKE_DOORBELL) {
> +             err = xhci_fake_doorbell(xhci, 1);
> +             if (err)
> +                     goto out_err;
> +
> +             err = xhci_start(xhci);
> +             if (err) {
> +                     err = -ENODEV;
> +                     goto out_err;
> +             }
>       }
> +
>       xhci->shared_hcd->state = HC_STATE_RUNNING;
>       xhci->cmd_ring_state = CMD_RING_STATE_RUNNING;
>  
> @@ -581,6 +629,9 @@ static int xhci_run_finished(struct xhci_hcd *xhci)
>       xhci_dbg_trace(xhci, trace_xhci_dbg_init,
>                       "Finished xhci_run for USB3 roothub");
>       return 0;

and another one here.

> +out_err:
> +     xhci_halt(xhci);
> +     return err;
>  }
>  
>  /*
> diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h
> index 9be7348..8c1faf4 100644
> --- a/drivers/usb/host/xhci.h
> +++ b/drivers/usb/host/xhci.h
> @@ -1631,6 +1631,7 @@ struct xhci_hcd {
>  #define XHCI_BROKEN_STREAMS  (1 << 19)
>  #define XHCI_PME_STUCK_QUIRK (1 << 20)
>  #define XHCI_MTK_HOST                (1 << 21)
> +#define XHCI_FAKE_DOORBELL   (1 << 22)
>       unsigned int            num_active_eps;
>       unsigned int            limit_active_eps;
>       /* There are two roothubs to keep track of bus suspend info for */
> diff --git a/include/linux/usb/xhci_pdriver.h 
> b/include/linux/usb/xhci_pdriver.h
> index 376654b..2b4ea5b 100644
> --- a/include/linux/usb/xhci_pdriver.h
> +++ b/include/linux/usb/xhci_pdriver.h
> @@ -22,6 +22,7 @@
>   */
>  struct usb_xhci_pdata {
>       unsigned        usb3_lpm_capable:1;
> +     unsigned        usb3_fake_doorbell:1;

missing kernel doc for this new quirk.

-- 
balbi

Attachment: signature.asc
Description: PGP signature

Reply via email to