2020-04-24 10:18:56

by Vinod Koul

[permalink] [raw]
Subject: [PATCH v10 0/5] usb: xhci: Add support for Renesas USB controllers

This series add support for Renesas USB controllers uPD720201 and uPD720202.
These require firmware to be loaded and in case devices have ROM those can
also be programmed if empty. If ROM is programmed, it runs from ROM as well.

This includes patches from Christian which supported these controllers w/o
ROM and later my patches for ROM support and debugfs hook for rom erase and
export of xhci-pci functions.

Changes in v10:
remove renesas_xhci_pci_probe and call renesas_xhci_check_request_fw and
also cleanup exit code along with it.

Changes in v9:
Make fw load a sync call and have single instance of probe execute,
elimating probe/remove races
Add quirk for renesas and use that for loading

Changes in v8:
Fix compile error reported by Kbuild-bot by making usb_hcd_pci_probe() take
const struct hc_driver * as argument

Changes in v7:
Make a single module which removes issues with module loading
Keep the renesas code in renesas file
Add hc_driver as argument for usb_hcd_pci_probe and modify hdc drivers to
pass this and not use driver_data
Use driver data for fw name
Remove code to check if we need to load firmware or not
remove multiple fw version support, we can do that with symlink in
userspace

Changes in v6:
Move the renesas code into a separate driver which invokes xhci-pci functions.

Changes in v5:
Added a debugfs rom erase patch, helps in debugging
Squashed patch 1 & 2 as requested by Mathias

Changes in v4:
Rollback the delay values as we got device failures

Changes in v3:
Dropped patch 2 as discussed with Christian
Removed aligned 8 bytes check
Change order for firmware search from highest version to lowest
Added entry for new firmware for device 0x14 as well
Add tested by Christian

Changes in v2:
used macros for timeout count and delay
removed renesas_fw_alive_check
cleaned renesas_fw_callback
removed recurion for renesas_fw_download
added MODULE_FIRMWARE
added comment for multiple fw order

Christian Lamparter (1):
usb: renesas-xhci: Add the renesas xhci driver

Vinod Koul (4):
usb: hci: add hc_driver as argument for usb_hcd_pci_probe
usb: xhci: Add support for Renesas controller with memory
usb: renesas-xhci: Add ROM loader for uPD720201
usb: xhci: provide a debugfs hook for erasing rom

drivers/usb/core/hcd-pci.c | 7 +-
drivers/usb/host/Makefile | 3 +-
drivers/usb/host/ehci-pci.c | 6 +-
drivers/usb/host/ohci-pci.c | 9 +-
drivers/usb/host/uhci-pci.c | 8 +-
drivers/usb/host/xhci-pci-renesas.c | 726 ++++++++++++++++++++++++++++
drivers/usb/host/xhci-pci.c | 42 +-
drivers/usb/host/xhci-pci.h | 16 +
drivers/usb/host/xhci.h | 1 +
include/linux/usb/hcd.h | 3 +-
10 files changed, 798 insertions(+), 23 deletions(-)
create mode 100644 drivers/usb/host/xhci-pci-renesas.c
create mode 100644 drivers/usb/host/xhci-pci.h

--
2.25.1


2020-04-24 10:19:18

by Vinod Koul

[permalink] [raw]
Subject: [PATCH v10 3/5] usb: xhci: Add support for Renesas controller with memory

Some rensas controller like uPD720201 and uPD720202 need firmware to be
loaded. Add these devices in table and invoke renesas firmware loader
functions to check and load the firmware into device memory when
required.

Signed-off-by: Vinod Koul <[email protected]>
---
drivers/usb/host/xhci-pci.c | 28 ++++++++++++++++++++++++++++
drivers/usb/host/xhci.h | 1 +
2 files changed, 29 insertions(+)

diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c
index b6c2f5c530e3..f26cf072836d 100644
--- a/drivers/usb/host/xhci-pci.c
+++ b/drivers/usb/host/xhci-pci.c
@@ -15,6 +15,7 @@

#include "xhci.h"
#include "xhci-trace.h"
+#include "xhci-pci.h"

#define SSIC_PORT_NUM 2
#define SSIC_PORT_CFG2 0x880c
@@ -319,6 +320,8 @@ static int xhci_pci_setup(struct usb_hcd *hcd)
return xhci_pci_reinit(xhci, pdev);
}

+static bool renesas_device;
+
/*
* We need to register our own PCI probe function (instead of the USB core's
* function) in order to create a second roothub under xHCI.
@@ -328,6 +331,16 @@ static int xhci_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
int retval;
struct xhci_hcd *xhci;
struct usb_hcd *hcd;
+ struct xhci_driver_data *driver_data;
+
+ renesas_device = false;
+ driver_data = (struct xhci_driver_data *)id->driver_data;
+ if (driver_data && driver_data->quirks & XHCI_RENESAS_FW_QUIRK) {
+ retval = renesas_xhci_check_request_fw(dev, id);
+ if (retval)
+ return retval;
+ renesas_device = true;
+ }

/* Prevent runtime suspending between USB-2 and USB-3 initialization */
pm_runtime_get_noresume(&dev->dev);
@@ -388,6 +401,9 @@ static void xhci_pci_remove(struct pci_dev *dev)
{
struct xhci_hcd *xhci;

+ if (renesas_device)
+ renesas_xhci_pci_exit(dev);
+
xhci = hcd_to_xhci(pci_get_drvdata(dev));
xhci->xhc_state |= XHCI_STATE_REMOVING;

@@ -540,14 +556,26 @@ static void xhci_pci_shutdown(struct usb_hcd *hcd)

/*-------------------------------------------------------------------------*/

+static const struct xhci_driver_data reneses_data = {
+ .quirks = XHCI_RENESAS_FW_QUIRK,
+ .firmware = "renesas_usb_fw.mem",
+};
+
/* PCI driver selection metadata; PCI hotplugging uses this */
static const struct pci_device_id pci_ids[] = {
+ { PCI_DEVICE(0x1912, 0x0014),
+ .driver_data = (unsigned long)&reneses_data,
+ },
+ { PCI_DEVICE(0x1912, 0x0015),
+ .driver_data = (unsigned long)&reneses_data,
+ },
/* handle any USB 3.0 xHCI controller */
{ PCI_DEVICE_CLASS(PCI_CLASS_SERIAL_USB_XHCI, ~0),
},
{ /* end: all zeroes */ }
};
MODULE_DEVICE_TABLE(pci, pci_ids);
+MODULE_FIRMWARE("renesas_usb_fw.mem");

/* pci driver glue; this is a "new style" PCI driver module */
static struct pci_driver xhci_pci_driver = {
diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h
index 3289bb516201..4047363c7423 100644
--- a/drivers/usb/host/xhci.h
+++ b/drivers/usb/host/xhci.h
@@ -1873,6 +1873,7 @@ struct xhci_hcd {
#define XHCI_DEFAULT_PM_RUNTIME_ALLOW BIT_ULL(33)
#define XHCI_RESET_PLL_ON_DISCONNECT BIT_ULL(34)
#define XHCI_SNPS_BROKEN_SUSPEND BIT_ULL(35)
+#define XHCI_RENESAS_FW_QUIRK BIT_ULL(36)

unsigned int num_active_eps;
unsigned int limit_active_eps;
--
2.25.1

2020-04-29 13:52:58

by Mathias Nyman

[permalink] [raw]
Subject: Re: [PATCH v10 3/5] usb: xhci: Add support for Renesas controller with memory

On 24.4.2020 13.14, Vinod Koul wrote:
> Some rensas controller like uPD720201 and uPD720202 need firmware to be
> loaded. Add these devices in table and invoke renesas firmware loader
> functions to check and load the firmware into device memory when
> required.
>
> Signed-off-by: Vinod Koul <[email protected]>
> ---
> drivers/usb/host/xhci-pci.c | 28 ++++++++++++++++++++++++++++
> drivers/usb/host/xhci.h | 1 +
> 2 files changed, 29 insertions(+)
>
> diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c
> index b6c2f5c530e3..f26cf072836d 100644
> --- a/drivers/usb/host/xhci-pci.c
> +++ b/drivers/usb/host/xhci-pci.c
> @@ -15,6 +15,7 @@
>
> #include "xhci.h"
> #include "xhci-trace.h"
> +#include "xhci-pci.h"
>
> #define SSIC_PORT_NUM 2
> #define SSIC_PORT_CFG2 0x880c
> @@ -319,6 +320,8 @@ static int xhci_pci_setup(struct usb_hcd *hcd)
> return xhci_pci_reinit(xhci, pdev);
> }
>
> +static bool renesas_device;

hmm, we shouldn't need this

> +
> /*
> * We need to register our own PCI probe function (instead of the USB core's
> * function) in order to create a second roothub under xHCI.
> @@ -328,6 +331,16 @@ static int xhci_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
> int retval;
> struct xhci_hcd *xhci;
> struct usb_hcd *hcd;
> + struct xhci_driver_data *driver_data;
> +
> + renesas_device = false;
> + driver_data = (struct xhci_driver_data *)id->driver_data;
> + if (driver_data && driver_data->quirks & XHCI_RENESAS_FW_QUIRK) {
> + retval = renesas_xhci_check_request_fw(dev, id);
> + if (retval)
> + return retval;
> + renesas_device = true;
> + }
>
> /* Prevent runtime suspending between USB-2 and USB-3 initialization */
> pm_runtime_get_noresume(&dev->dev);
> @@ -388,6 +401,9 @@ static void xhci_pci_remove(struct pci_dev *dev)
> {
> struct xhci_hcd *xhci;
>
> + if (renesas_device)
> + renesas_xhci_pci_exit(dev);
> +

Ah, I see, what we really should do is make sure the quirks in the driver data get
added to xhci->quirks, and then just check for the correct quirk in xhci_pci_remove.

if (xhci->quirks & XHCI_RENESAS_FW_QUIRK)
renesas_xhci_pci_exit(dev);


Heikki Krogerus did some work on this a long time ago, below code is based on his
work. It needs to be added:
diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c
index f26cf072836d..5ae4fc10fc31 100644
--- a/drivers/usb/host/xhci-pci.c
+++ b/drivers/usb/host/xhci-pci.c
@@ -88,8 +88,16 @@ static int xhci_pci_reinit(struct xhci_hcd *xhci, struct pci_dev *pdev)

static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci)
{
- struct pci_dev *pdev = to_pci_dev(dev);
+ struct pci_dev *pdev = to_pci_dev(dev);
+ struct xhci_driver_data *driver_data;
+ const struct pci_device_id *id;

+ id = pci_match_id(pdev->driver->id_table, pdev);
+
+ if (id && id->driver_data) {
+ driver_data = (struct xhci_driver_data *)id->driver_data;
+ xhci->quirks |= driver_data->quirks;
+ }
/* Look for vendor-specific quirks */
if (pdev->vendor == PCI_VENDOR_ID_FRESCO_LOGIC &&
(pdev->device == PCI_DEVICE_ID_FRESCO_LOGIC_PDK ||


-Mathias

2020-04-29 14:30:59

by Vinod Koul

[permalink] [raw]
Subject: Re: [PATCH v10 3/5] usb: xhci: Add support for Renesas controller with memory

On 29-04-20, 16:53, Mathias Nyman wrote:
> On 24.4.2020 13.14, Vinod Koul wrote:
> > Some rensas controller like uPD720201 and uPD720202 need firmware to be
> > loaded. Add these devices in table and invoke renesas firmware loader
> > functions to check and load the firmware into device memory when
> > required.
> >
> > Signed-off-by: Vinod Koul <[email protected]>
> > ---
> > drivers/usb/host/xhci-pci.c | 28 ++++++++++++++++++++++++++++
> > drivers/usb/host/xhci.h | 1 +
> > 2 files changed, 29 insertions(+)
> >
> > diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c
> > index b6c2f5c530e3..f26cf072836d 100644
> > --- a/drivers/usb/host/xhci-pci.c
> > +++ b/drivers/usb/host/xhci-pci.c
> > @@ -15,6 +15,7 @@
> >
> > #include "xhci.h"
> > #include "xhci-trace.h"
> > +#include "xhci-pci.h"
> >
> > #define SSIC_PORT_NUM 2
> > #define SSIC_PORT_CFG2 0x880c
> > @@ -319,6 +320,8 @@ static int xhci_pci_setup(struct usb_hcd *hcd)
> > return xhci_pci_reinit(xhci, pdev);
> > }
> >
> > +static bool renesas_device;
>
> hmm, we shouldn't need this
>
> > +
> > /*
> > * We need to register our own PCI probe function (instead of the USB core's
> > * function) in order to create a second roothub under xHCI.
> > @@ -328,6 +331,16 @@ static int xhci_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
> > int retval;
> > struct xhci_hcd *xhci;
> > struct usb_hcd *hcd;
> > + struct xhci_driver_data *driver_data;
> > +
> > + renesas_device = false;
> > + driver_data = (struct xhci_driver_data *)id->driver_data;
> > + if (driver_data && driver_data->quirks & XHCI_RENESAS_FW_QUIRK) {
> > + retval = renesas_xhci_check_request_fw(dev, id);
> > + if (retval)
> > + return retval;
> > + renesas_device = true;
> > + }
> >
> > /* Prevent runtime suspending between USB-2 and USB-3 initialization */
> > pm_runtime_get_noresume(&dev->dev);
> > @@ -388,6 +401,9 @@ static void xhci_pci_remove(struct pci_dev *dev)
> > {
> > struct xhci_hcd *xhci;
> >
> > + if (renesas_device)
> > + renesas_xhci_pci_exit(dev);
> > +
>
> Ah, I see, what we really should do is make sure the quirks in the driver data get
> added to xhci->quirks, and then just check for the correct quirk in xhci_pci_remove.

Ah sure that does sound better, I will update this as well and send an
update with these changes

>
> if (xhci->quirks & XHCI_RENESAS_FW_QUIRK)
> renesas_xhci_pci_exit(dev);
>
>
> Heikki Krogerus did some work on this a long time ago, below code is based on his
> work. It needs to be added:
> diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c
> index f26cf072836d..5ae4fc10fc31 100644
> --- a/drivers/usb/host/xhci-pci.c
> +++ b/drivers/usb/host/xhci-pci.c
> @@ -88,8 +88,16 @@ static int xhci_pci_reinit(struct xhci_hcd *xhci, struct pci_dev *pdev)
>
> static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci)
> {
> - struct pci_dev *pdev = to_pci_dev(dev);
> + struct pci_dev *pdev = to_pci_dev(dev);
> + struct xhci_driver_data *driver_data;
> + const struct pci_device_id *id;
>
> + id = pci_match_id(pdev->driver->id_table, pdev);
> +
> + if (id && id->driver_data) {
> + driver_data = (struct xhci_driver_data *)id->driver_data;
> + xhci->quirks |= driver_data->quirks;
> + }
> /* Look for vendor-specific quirks */
> if (pdev->vendor == PCI_VENDOR_ID_FRESCO_LOGIC &&
> (pdev->device == PCI_DEVICE_ID_FRESCO_LOGIC_PDK ||
>
>
> -Mathias

--
~Vinod

2020-04-30 06:23:24

by Vinod Koul

[permalink] [raw]
Subject: Re: [PATCH v10 3/5] usb: xhci: Add support for Renesas controller with memory

On 29-04-20, 19:58, Vinod Koul wrote:
> On 29-04-20, 16:53, Mathias Nyman wrote:
> > On 24.4.2020 13.14, Vinod Koul wrote:

> > > /* Prevent runtime suspending between USB-2 and USB-3 initialization */
> > > pm_runtime_get_noresume(&dev->dev);
> > > @@ -388,6 +401,9 @@ static void xhci_pci_remove(struct pci_dev *dev)
> > > {
> > > struct xhci_hcd *xhci;
> > >
> > > + if (renesas_device)
> > > + renesas_xhci_pci_exit(dev);
> > > +
> >
> > Ah, I see, what we really should do is make sure the quirks in the driver data get
> > added to xhci->quirks, and then just check for the correct quirk in xhci_pci_remove.
>
> Ah sure that does sound better, I will update this as well and send an
> update with these changes

This works for me.. But I have kept the code as in the xhci_pci_probe(),
ofcourse removed bool renesas_device.

the xhci is not valid before invoking renesas_xhci_check_request_fw().
Is there another way to get xhci from dev without calling
usb_hcd_pci_probe().
xhci = hcd_to_xhci(hcd) doesn't seem to work before that!

--
~Vinod

2020-04-30 08:17:03

by Mathias Nyman

[permalink] [raw]
Subject: Re: [PATCH v10 3/5] usb: xhci: Add support for Renesas controller with memory

On 30.4.2020 9.20, Vinod Koul wrote:
> On 29-04-20, 19:58, Vinod Koul wrote:
>> On 29-04-20, 16:53, Mathias Nyman wrote:
>>> On 24.4.2020 13.14, Vinod Koul wrote:
>
>>>> /* Prevent runtime suspending between USB-2 and USB-3 initialization */
>>>> pm_runtime_get_noresume(&dev->dev);
>>>> @@ -388,6 +401,9 @@ static void xhci_pci_remove(struct pci_dev *dev)
>>>> {
>>>> struct xhci_hcd *xhci;
>>>>
>>>> + if (renesas_device)
>>>> + renesas_xhci_pci_exit(dev);
>>>> +
>>>
>>> Ah, I see, what we really should do is make sure the quirks in the driver data get
>>> added to xhci->quirks, and then just check for the correct quirk in xhci_pci_remove.
>>
>> Ah sure that does sound better, I will update this as well and send an
>> update with these changes
>
> This works for me.. But I have kept the code as in the xhci_pci_probe(),
> ofcourse removed bool renesas_device.

That's fine, xhci is just hcd->hcd_priv, and it doesn't exists before
usb_hcd_pci_probe() is called

usb_hcd_pci_probe()
usb_create_hcd()
hcd = kzalloc(sizeof(*hcd) + driver->hcd_priv_size, GFP_KERNEL);

-Mathias


2020-04-30 09:18:30

by Vinod Koul

[permalink] [raw]
Subject: Re: [PATCH v10 3/5] usb: xhci: Add support for Renesas controller with memory

On 30-04-20, 11:16, Mathias Nyman wrote:
> On 30.4.2020 9.20, Vinod Koul wrote:
> > On 29-04-20, 19:58, Vinod Koul wrote:
> >> On 29-04-20, 16:53, Mathias Nyman wrote:
> >>> On 24.4.2020 13.14, Vinod Koul wrote:
> >
> >>>> /* Prevent runtime suspending between USB-2 and USB-3 initialization */
> >>>> pm_runtime_get_noresume(&dev->dev);
> >>>> @@ -388,6 +401,9 @@ static void xhci_pci_remove(struct pci_dev *dev)
> >>>> {
> >>>> struct xhci_hcd *xhci;
> >>>>
> >>>> + if (renesas_device)
> >>>> + renesas_xhci_pci_exit(dev);
> >>>> +
> >>>
> >>> Ah, I see, what we really should do is make sure the quirks in the driver data get
> >>> added to xhci->quirks, and then just check for the correct quirk in xhci_pci_remove.
> >>
> >> Ah sure that does sound better, I will update this as well and send an
> >> update with these changes
> >
> > This works for me.. But I have kept the code as in the xhci_pci_probe(),
> > ofcourse removed bool renesas_device.
>
> That's fine, xhci is just hcd->hcd_priv, and it doesn't exists before
> usb_hcd_pci_probe() is called
>
> usb_hcd_pci_probe()
> usb_create_hcd()
> hcd = kzalloc(sizeof(*hcd) + driver->hcd_priv_size, GFP_KERNEL);

Right, thanks for confirming

--
~Vinod