diff mbox

usb: dwc3: host: inherit dma configuration from parent dev

Message ID 20160908122810.GA14132@b29397-desktop (mailing list archive)
State New, archived
Headers show

Commit Message

Peter Chen Sept. 8, 2016, 12:28 p.m. UTC
On Thu, Sep 08, 2016 at 12:17:21PM +0200, Arnd Bergmann wrote:
> On Thursday, September 8, 2016 12:43:06 PM CEST Felipe Balbi wrote:
> > Arnd Bergmann <arnd@arndb.de> writes:
> > > On Thursday, September 8, 2016 11:29:04 AM CEST Felipe Balbi wrote:
> > >> > If we do that, we have to put child devices of the dwc3 devices into
> > >> > the platform glue, and it also breaks those dwc3 devices that don't
> > >> > have a parent driver.
> > >> 
> > >> Well, this is easy to fix:
> > >> 
> > >>         if (dwc->dev->parent) {
> > >>                 dwc->sysdev = dwc->dev->parent;
> > >>         } else {
> > >>                 dev_info(dwc->dev, "Please provide a glue layer!\n");
> > >>                 dwc->sysdev = dwc->dev;
> > >>         }
> > >
> > > I don't understand. Do you mean we should have an extra level of
> > > stacking and splitting "static struct platform_driver dwc3_driver"
> > > in two so instead of
> > >
> > >       "qcom,dwc3" -> "snps,dwc3" (usb_bus.sysdev) -> "xhci" (usb_bus.dev)
> > >
> > > we do this?
> > >
> > >       "qcom,dwc3" -> "snps,dwc3" (usb_bus.sysdev) -> "dwc3-glue" -> "xhci" (usb_bus.dev)
> > 
> > no 
> > 
> > If we have a parent device, use that as sysdev, otherwise use self as
> > sysdev.
> 
> But there is often a parent device in DT, as the xhci device is
> attached to some internal bus that gets turned into a platform_device
> as well, so checking whether there is a parent will get the wrong
> device node.

From my point, all platform and firmware information at dwc3 are
correct, so we don't need to change dwc3/core.c, only changing for
xhci-plat.c is ok.

At above changes, the root hub's of_node equals to xhci-hcd sysdev's
of_node, which is from firmware or from its parent (it is dwc3 core
device).

> 
> > > That sounds a bit clumsy for the sake of consistency with PCI.
> > > The advantage is that xhci can always use the grandparent device
> > > as sysdev whenever it isn't probed through PCI or firmware
> > > itself, but the purpose of the dwc3-glue is otherwise questionable.
> > >
> > > How about adding a 'compatible="snps,dwc3-pci"' property for the dwc3
> > > device when that is created from the PCI driver and checking for that
> > > with the device property interface instead? If it's "snps,dwc3"
> > > we use the device itself while for "snps,dwc3-pci", we use the parent?
> > 

For pci glue device, it is always the parent for dwc3 core device.
In your patch, you may not need to split pci or non-pci, just using
if (dev->parent).

> > Any reason why we wouldn't use e.g. dwc3-omap.dev as sysdev?
> 
> That would be incompatible with the USB binding, as the sysdev
> is assumed to be a USB host controller with #address-cells=<1>
> and #size-cells=<0> in order to hold the child devices, for
> example:
> 
> / {
>      omap_dwc3_1: omap_dwc3_1@48880000 {
>         compatible = "ti,dwc3";
>         #address-cells = <1>;
>         #size-cells = <1>;
>         ranges;
>         usb1: usb@48890000 {
>                 compatible = "snps,dwc3";
>                 reg = <0x48890000 0x17000>;
>                 #address-cells = <1>;
>                 #size-cells = <0>;
>                 interrupts = <GIC_SPI 71 IRQ_TYPE_LEVEL_HIGH>,
>                              <GIC_SPI 71 IRQ_TYPE_LEVEL_HIGH>,
>                              <GIC_SPI 72 IRQ_TYPE_LEVEL_HIGH>;
>                 interrupt-names = "peripheral",
>                                   "host",
>                                   "otg";
>                 phys = <&usb2_phy1>, <&usb3_phy1>;
>                 phy-names = "usb2-phy", "usb3-phy";
> 
>                 hub@1 {
>                         compatible = "usb5e3,608";
>                         reg = <1>;
>                         #address-cells = <1>;
>                         #size-cells = <0>;
> 
>                         ethernet@1 {
>                                 compatible = "usb424,ec00";
>                                 mac-address = [00 11 22 33 44 55];
>                                 reg = <1>;
>                         };
>                 };
>         };
> };
> 

With my above changes, the hub of_node should be found since it is
child of root hub's of_node which is the dwc3's of_node.

> It's also the node that contains the "phys" properties and
> presumably other properties like "otg-rev", "maximum-speed"
> etc.
> 

This information is described at dwc3 core device of_node, and be
handled at dwc3/core.c

Comments

Arnd Bergmann Sept. 8, 2016, 12:52 p.m. UTC | #1
On Thursday, September 8, 2016 8:28:10 PM CEST Peter Chen wrote:
> On Thu, Sep 08, 2016 at 12:17:21PM +0200, Arnd Bergmann wrote:
> > On Thursday, September 8, 2016 12:43:06 PM CEST Felipe Balbi wrote:
> > > Arnd Bergmann <arnd@arndb.de> writes:
> > > > On Thursday, September 8, 2016 11:29:04 AM CEST Felipe Balbi wrote:
> > > If we have a parent device, use that as sysdev, otherwise use self as
> > > sysdev.
> > 
> > But there is often a parent device in DT, as the xhci device is
> > attached to some internal bus that gets turned into a platform_device
> > as well, so checking whether there is a parent will get the wrong
> > device node.
> 
> From my point, all platform and firmware information at dwc3 are
> correct, so we don't need to change dwc3/core.c, only changing for
> xhci-plat.c is ok.

Ok, thanks. That leaves the PCI glue, right?

> diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
> index d2e3f65..563600b 100644
> --- a/drivers/usb/core/hcd.c
> +++ b/drivers/usb/core/hcd.c
> @@ -1118,7 +1118,7 @@ static int register_root_hub(struct usb_hcd *hcd)
>  		/* Did the HC die before the root hub was registered? */
>  		if (HCD_DEAD(hcd))
>  			usb_hc_died (hcd);	/* This time clean up */
> -		usb_dev->dev.of_node = parent_dev->of_node;
> +		usb_dev->dev.of_node = parent_dev->sysdev->of_node;
>  	}
>  	mutex_unlock(&usb_bus_idr_lock);
> 
> At above changes, the root hub's of_node equals to xhci-hcd sysdev's
> of_node, which is from firmware or from its parent (it is dwc3 core
> device).

Just to make sure I understand you right:

in the qcom,dwc3 -> dwc3 -> xhci hierarchy, this would be the
dwc3 device, not the qcom,dwc3 device.

> > > > That sounds a bit clumsy for the sake of consistency with PCI.
> > > > The advantage is that xhci can always use the grandparent device
> > > > as sysdev whenever it isn't probed through PCI or firmware
> > > > itself, but the purpose of the dwc3-glue is otherwise questionable.
> > > >
> > > > How about adding a 'compatible="snps,dwc3-pci"' property for the dwc3
> > > > device when that is created from the PCI driver and checking for that
> > > > with the device property interface instead? If it's "snps,dwc3"
> > > > we use the device itself while for "snps,dwc3-pci", we use the parent?
> > > 
> 
> For pci glue device, it is always the parent for dwc3 core device.
> In your patch, you may not need to split pci or non-pci, just using
> if (dev->parent).

Here we have the pci-dwc3 -> dwc3 -> xhci hierarchy, and we want
sysdev to point to pci-dwc3, not dwc3!

The point is that the pci_dev is where we have the dma settings
and (optionally) additional DT or ACPI data for that device.

	Arnd
Grygorii Strashko Sept. 8, 2016, 12:59 p.m. UTC | #2
On 09/08/2016 03:28 PM, Peter Chen wrote:
> On Thu, Sep 08, 2016 at 12:17:21PM +0200, Arnd Bergmann wrote:
>> On Thursday, September 8, 2016 12:43:06 PM CEST Felipe Balbi wrote:
>>> Arnd Bergmann <arnd@arndb.de> writes:
>>>> On Thursday, September 8, 2016 11:29:04 AM CEST Felipe Balbi wrote:
>>>>>> If we do that, we have to put child devices of the dwc3 devices into
>>>>>> the platform glue, and it also breaks those dwc3 devices that don't
>>>>>> have a parent driver.
>>>>>
>>>>> Well, this is easy to fix:
>>>>>
>>>>>         if (dwc->dev->parent) {
>>>>>                 dwc->sysdev = dwc->dev->parent;
>>>>>         } else {
>>>>>                 dev_info(dwc->dev, "Please provide a glue layer!\n");
>>>>>                 dwc->sysdev = dwc->dev;
>>>>>         }
>>>>
>>>> I don't understand. Do you mean we should have an extra level of
>>>> stacking and splitting "static struct platform_driver dwc3_driver"
>>>> in two so instead of
>>>>
>>>>       "qcom,dwc3" -> "snps,dwc3" (usb_bus.sysdev) -> "xhci" (usb_bus.dev)
>>>>
>>>> we do this?
>>>>
>>>>       "qcom,dwc3" -> "snps,dwc3" (usb_bus.sysdev) -> "dwc3-glue" -> "xhci" (usb_bus.dev)
>>>
>>> no 
>>>
>>> If we have a parent device, use that as sysdev, otherwise use self as
>>> sysdev.
>>
>> But there is often a parent device in DT, as the xhci device is
>> attached to some internal bus that gets turned into a platform_device
>> as well, so checking whether there is a parent will get the wrong
>> device node.
> 
> From my point, all platform and firmware information at dwc3 are
> correct, so we don't need to change dwc3/core.c, only changing for
> xhci-plat.c is ok.
> 
> diff --git a/drivers/usb/host/xhci-plat.c b/drivers/usb/host/xhci-plat.c
> index ed56bf9..fd57c0d 100644
> --- a/drivers/usb/host/xhci-plat.c
> +++ b/drivers/usb/host/xhci-plat.c
> @@ -145,6 +145,7 @@ static int xhci_plat_probe(struct platform_device *pdev)
>  	struct clk              *clk;
>  	int			ret;
>  	int			irq;
> +	struct device *dev = &pdev->dev, *sysdev;
>  
>  	if (usb_disabled())
>  		return -ENODEV;
> @@ -155,6 +156,12 @@ static int xhci_plat_probe(struct platform_device *pdev)
>  	if (irq < 0)
>  		return -ENODEV;
>  
> +	if (dev->parent) {
> +		sysdev = dev->parent;
> +	} else {
> +        	sysdev = dev;
> +	}
> +

Shouldn't we be more careful with that?

armada-375.dtsi

	soc {
		compatible = "marvell,armada375-mbus", "simple-bus";

		internal-regs {
			compatible = "simple-bus";

			usb3@58000 {
				compatible = "marvell,armada-375-xhci";
				reg = <0x58000 0x20000>,<0x5b880 0x80>;
				interrupts = <GIC_SPI 16 IRQ_TYPE_LEVEL_HIGH>;
				clocks = <&gateclk 16>;
				phys = <&usbcluster PHY_TYPE_USB3>;
				phy-names = "usb";
				status = "disabled";
			};


What will be the parent dev in above case?
Peter Chen Sept. 9, 2016, 1:37 a.m. UTC | #3
On Thu, Sep 08, 2016 at 02:52:29PM +0200, Arnd Bergmann wrote:
> On Thursday, September 8, 2016 8:28:10 PM CEST Peter Chen wrote:
> > On Thu, Sep 08, 2016 at 12:17:21PM +0200, Arnd Bergmann wrote:
> > > On Thursday, September 8, 2016 12:43:06 PM CEST Felipe Balbi wrote:
> > > > Arnd Bergmann <arnd@arndb.de> writes:
> > > > > On Thursday, September 8, 2016 11:29:04 AM CEST Felipe Balbi wrote:
> > > > If we have a parent device, use that as sysdev, otherwise use self as
> > > > sysdev.
> > > 
> > > But there is often a parent device in DT, as the xhci device is
> > > attached to some internal bus that gets turned into a platform_device
> > > as well, so checking whether there is a parent will get the wrong
> > > device node.
> > 
> > From my point, all platform and firmware information at dwc3 are
> > correct, so we don't need to change dwc3/core.c, only changing for
> > xhci-plat.c is ok.
> 
> Ok, thanks. That leaves the PCI glue, right?

If pci's firmware information can only get from dwc3-pci, I was wrong.
I am almost sure your patch covers all 3 cases. dwc3->sysdev covers
dwc3 core and gadget side, hcd->self.sysdev cover host side. The only
possible improvement may be how to detect pci device.

> 
> > diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
> > index d2e3f65..563600b 100644
> > --- a/drivers/usb/core/hcd.c
> > +++ b/drivers/usb/core/hcd.c
> > @@ -1118,7 +1118,7 @@ static int register_root_hub(struct usb_hcd *hcd)
> >  		/* Did the HC die before the root hub was registered? */
> >  		if (HCD_DEAD(hcd))
> >  			usb_hc_died (hcd);	/* This time clean up */
> > -		usb_dev->dev.of_node = parent_dev->of_node;
> > +		usb_dev->dev.of_node = parent_dev->sysdev->of_node;
> >  	}
> >  	mutex_unlock(&usb_bus_idr_lock);
> > 
> > At above changes, the root hub's of_node equals to xhci-hcd sysdev's
> > of_node, which is from firmware or from its parent (it is dwc3 core
> > device).
> 
> Just to make sure I understand you right:
> 
> in the qcom,dwc3 -> dwc3 -> xhci hierarchy, this would be the
> dwc3 device, not the qcom,dwc3 device.
> 

Yes, since there is a DT node for dwc3, and firmware information is there,
that's why the original patch (Grygorii Strashko's) can work.
Peter Chen Sept. 9, 2016, 1:52 a.m. UTC | #4
On Thu, Sep 08, 2016 at 03:59:19PM +0300, Grygorii Strashko wrote:
> On 09/08/2016 03:28 PM, Peter Chen wrote:
> > On Thu, Sep 08, 2016 at 12:17:21PM +0200, Arnd Bergmann wrote:
> >> On Thursday, September 8, 2016 12:43:06 PM CEST Felipe Balbi wrote:
> >>> Arnd Bergmann <arnd@arndb.de> writes:
> >>>> On Thursday, September 8, 2016 11:29:04 AM CEST Felipe Balbi wrote:
> >>>>>> If we do that, we have to put child devices of the dwc3 devices into
> >>>>>> the platform glue, and it also breaks those dwc3 devices that don't
> >>>>>> have a parent driver.
> >>>>>
> >>>>> Well, this is easy to fix:
> >>>>>
> >>>>>         if (dwc->dev->parent) {
> >>>>>                 dwc->sysdev = dwc->dev->parent;
> >>>>>         } else {
> >>>>>                 dev_info(dwc->dev, "Please provide a glue layer!\n");
> >>>>>                 dwc->sysdev = dwc->dev;
> >>>>>         }
> >>>>
> >>>> I don't understand. Do you mean we should have an extra level of
> >>>> stacking and splitting "static struct platform_driver dwc3_driver"
> >>>> in two so instead of
> >>>>
> >>>>       "qcom,dwc3" -> "snps,dwc3" (usb_bus.sysdev) -> "xhci" (usb_bus.dev)
> >>>>
> >>>> we do this?
> >>>>
> >>>>       "qcom,dwc3" -> "snps,dwc3" (usb_bus.sysdev) -> "dwc3-glue" -> "xhci" (usb_bus.dev)
> >>>
> >>> no 
> >>>
> >>> If we have a parent device, use that as sysdev, otherwise use self as
> >>> sysdev.
> >>
> >> But there is often a parent device in DT, as the xhci device is
> >> attached to some internal bus that gets turned into a platform_device
> >> as well, so checking whether there is a parent will get the wrong
> >> device node.
> > 
> > From my point, all platform and firmware information at dwc3 are
> > correct, so we don't need to change dwc3/core.c, only changing for
> > xhci-plat.c is ok.
> > 
> > diff --git a/drivers/usb/host/xhci-plat.c b/drivers/usb/host/xhci-plat.c
> > index ed56bf9..fd57c0d 100644
> > --- a/drivers/usb/host/xhci-plat.c
> > +++ b/drivers/usb/host/xhci-plat.c
> > @@ -145,6 +145,7 @@ static int xhci_plat_probe(struct platform_device *pdev)
> >  	struct clk              *clk;
> >  	int			ret;
> >  	int			irq;
> > +	struct device *dev = &pdev->dev, *sysdev;
> >  
> >  	if (usb_disabled())
> >  		return -ENODEV;
> > @@ -155,6 +156,12 @@ static int xhci_plat_probe(struct platform_device *pdev)
> >  	if (irq < 0)
> >  		return -ENODEV;
> >  
> > +	if (dev->parent) {
> > +		sysdev = dev->parent;
> > +	} else {
> > +        	sysdev = dev;
> > +	}
> > +
> 
> Shouldn't we be more careful with that?
> 

Above code does not consider pci device case, Arnd's patch covers
all cases.

> armada-375.dtsi
> 
> 	soc {
> 		compatible = "marvell,armada375-mbus", "simple-bus";
> 
> 		internal-regs {
> 			compatible = "simple-bus";
> 
> 			usb3@58000 {
> 				compatible = "marvell,armada-375-xhci";
> 				reg = <0x58000 0x20000>,<0x5b880 0x80>;
> 				interrupts = <GIC_SPI 16 IRQ_TYPE_LEVEL_HIGH>;
> 				clocks = <&gateclk 16>;
> 				phys = <&usbcluster PHY_TYPE_USB3>;
> 				phy-names = "usb";
> 				status = "disabled";
> 			};
> 
> 
> What will be the parent dev in above case?
> 

In this case, no parent dev for above case, it will use itself as sysdev
since it has of_node at dts.
diff mbox

Patch

diff --git a/drivers/usb/host/xhci-plat.c b/drivers/usb/host/xhci-plat.c
index ed56bf9..fd57c0d 100644
--- a/drivers/usb/host/xhci-plat.c
+++ b/drivers/usb/host/xhci-plat.c
@@ -145,6 +145,7 @@  static int xhci_plat_probe(struct platform_device *pdev)
 	struct clk              *clk;
 	int			ret;
 	int			irq;
+	struct device *dev = &pdev->dev, *sysdev;
 
 	if (usb_disabled())
 		return -ENODEV;
@@ -155,6 +156,12 @@  static int xhci_plat_probe(struct platform_device *pdev)
 	if (irq < 0)
 		return -ENODEV;
 
+	if (dev->parent) {
+		sysdev = dev->parent;
+	} else {
+        	sysdev = dev;
+	}
+
 	/* Try to set 64-bit DMA first */
 	if (WARN_ON(!pdev->dev.dma_mask))
 		/* Platform did not initialize dma_mask */
@@ -170,7 +177,8 @@  static int xhci_plat_probe(struct platform_device *pdev)
 			return ret;
 	}
 
-	hcd = usb_create_hcd(driver, &pdev->dev, dev_name(&pdev->dev));
+	hcd = __usb_create_hcd(driver, sysdev, &pdev->dev,
+			dev_name(&pdev->dev), NULL);
 	if (!hcd)
 		return -ENOMEM;
 
diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
index d2e3f65..563600b 100644
--- a/drivers/usb/core/hcd.c
+++ b/drivers/usb/core/hcd.c
@@ -1118,7 +1118,7 @@  static int register_root_hub(struct usb_hcd *hcd)
 		/* Did the HC die before the root hub was registered? */
 		if (HCD_DEAD(hcd))
 			usb_hc_died (hcd);	/* This time clean up */
-		usb_dev->dev.of_node = parent_dev->of_node;
+		usb_dev->dev.of_node = parent_dev->sysdev->of_node;
 	}
 	mutex_unlock(&usb_bus_idr_lock);