Re: [PATCH] usb: xhci: handle uPD720201 and uPD720202 w/o ROM
From: Christian Lamparter
Date: Mon Jun 20 2016 - 11:35:03 EST
On Wednesday, June 08, 2016 12:14:57 AM Christian Lamparter wrote:
> This patch adds a firmware check for the uPD720201K8-711-BAC-A
> and uPD720202K8-711-BAA-A variant. Both of these chips are listed
> in Renesas' R19UH0078EJ0500 Rev.5.00 "User's Manual: Hardware" as
> devices which need a firmware in order to work as they do not have
> support to load the firmware from an external ROM.
>
> Currently, the xhci-pci driver is unable to initialize the hcd in
> this case. Instead it will wait for 30 seconds and cause a timeout
> in xhci_handshake() and fails.
>
> [ 5.116990] xhci_hcd 0000:45:00.0: new USB bus registered ...
> [ 32.335215] xhci_hcd 0000:45:00.0: can't setup: -110
> [ 32.340179] xhci_hcd 0000:45:00.0: USB bus 2 deregistered
> [ 32.345587] xhci_hcd 0000:45:00.0: init 0000:45:00.0 fail, -110
> [ 32.351496] xhci_hcd: probe of 0000:45:00.0 failed with error -110
>
> Cc: Yoshihiro Shimoda <yoshihiro.shimoda.uh@xxxxxxxxxxx>
> Signed-off-by: Christian Lamparter <chunkeey@xxxxxxxxx>
Hello?
Are there any news on this? Or is there anything else that I'm missing
which blocks this patch? If it's because the device won't be working
either with this patch, then please let me know. If Renesas is willing
to add the uPD720201/2 firmware (Like they did for their R-Car controllers)
to linux-firmware, I can write the necessary firmware loader from
the PDF for this device and put it into xhci-quirks.
Regards,
Christian
> ---
> drivers/usb/host/xhci-pci.c | 59 +++++++++++++++++++++++++++++++++++++++++++++
> 1 file changed, 59 insertions(+)
>
> diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c
> index 48672fa..3271a81 100644
> --- a/drivers/usb/host/xhci-pci.c
> +++ b/drivers/usb/host/xhci-pci.c
> @@ -207,6 +207,55 @@ static void xhci_pme_acpi_rtd3_enable(struct pci_dev *dev)
> static void xhci_pme_acpi_rtd3_enable(struct pci_dev *dev) { }
> #endif /* CONFIG_ACPI */
>
> +static int renesas_check_if_fw_dl_is_needed(struct pci_dev *pdev)
> +{
> + int err;
> + u8 fw_state;
> +
> + /*
> + * Only the uPD720201K8-711-BAC-A or uPD720202K8-711-BAA-A
> + * are listed in R19UH0078EJ0500 Rev.5.00 as devices which
> + * need a firmware in order to work.
> + *
> + * - uPD720202 ES 2.0 sample & CS sample & Mass product, ID is 2.
> + * - uPD720201 ES 2.0 sample whose revision ID is 2.
> + * - uPD720201 ES 2.1 sample & CS sample & Mass product, ID is 3.
> + */
> + if (!((pdev->vendor == PCI_VENDOR_ID_RENESAS) &&
> + ((pdev->device == 0x0015 && pdev->revision == 0x02) ||
> + (pdev->device == 0x0014 &&
> + (pdev->revision == 0x02 || pdev->revision == 0x03)))))
> + return 0;
> +
> + /*
> + * Test if the firmware was uploaded and is running.
> + * As most BIOSes will initialize the device for us.
> + */
> + err = pci_read_config_byte(pdev, 0xf4, &fw_state);
> + if (err)
> + return pcibios_err_to_errno(err);
> +
> + /* Check the "Result Code" Bits (6:4) and act accordingly */
> + switch (fw_state & 0x70) {
> + case 0: /* No result yet */
> + dev_err(&pdev->dev, "FW is not ready/loaded yet.");
> + return -ENODEV;
> +
> + case BIT(4): /* Success, device should be working. */
> + dev_dbg(&pdev->dev, "FW is ready.");
> + return 0;
> +
> + case BIT(5): /* Error State */
> + dev_err(&pdev->dev, "HW is in an error state.");
> + return -ENODEV;
> +
> + default: /* All other states are marked as "Reserved states" */
> + dev_err(&pdev->dev, "HW is in an invalid state (%x).",
> + (fw_state & 0x70) >> 4);
> + return -EINVAL;
> + }
> +}
> +
> /* called during probe() after chip reset completes */
> static int xhci_pci_setup(struct usb_hcd *hcd)
> {
> @@ -246,6 +295,11 @@ static int xhci_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
> struct hc_driver *driver;
> struct usb_hcd *hcd;
>
> + /* Check if this device is a RENESAS uPD720201/2 device. */
> + retval = renesas_check_if_fw_dl_is_needed(dev);
> + if (retval)
> + return retval;
> +
> driver = (struct hc_driver *)id->driver_data;
>
> /* Prevent runtime suspending between USB-2 and USB-3 initialization */
> @@ -424,6 +478,11 @@ static int xhci_pci_resume(struct usb_hcd *hcd, bool hibernated)
> if (pdev->vendor == PCI_VENDOR_ID_INTEL)
> usb_enable_intel_xhci_ports(pdev);
>
> + /* Check if this device is a RENESAS uPD720201/2 device. */
> + retval = renesas_check_if_fw_dl_is_needed(pdev);
> + if (retval)
> + return retval;
> +
> if (xhci->quirks & XHCI_SSIC_PORT_UNUSED)
> xhci_ssic_port_unused_quirk(hcd, false);
>
>