All of lore.kernel.org
 help / color / mirror / Atom feed
From: Neil Armstrong <narmstrong@baylibre.com>
To: Martin Blumenstingl <martin.blumenstingl@googlemail.com>
Cc: gregkh@linuxfoundation.org, hminas@synopsys.com,
	balbi@kernel.org, kishon@ti.com,
	linux-amlogic@lists.infradead.org, linux-usb@vger.kernel.org,
	linux-kernel@vger.kernel.org,
	linux-arm-kernel@lists.infradead.org
Subject: Re: [PATCH v2 8/8] usb: dwc3: Add Amlogic G12A DWC3 glue
Date: Wed, 13 Mar 2019 14:07:34 +0100	[thread overview]
Message-ID: <6f84d21f-1093-185f-dd70-b470bfa9c7da@baylibre.com> (raw)
In-Reply-To: <CAFBinCAWEEKdsG2ZGCsFd1XyTUerAJpxJFEGGF-6j3UmpOmc=Q@mail.gmail.com>

On 11/03/2019 22:56, Martin Blumenstingl wrote:
> Hi Neil,
> 
> On Mon, Mar 4, 2019 at 11:41 AM Neil Armstrong <narmstrong@baylibre.com> wrote:
> [...]
>> +static void dwc3_meson_g12a_usb_init_mode(struct dwc3_meson_g12a *priv)
>> +{
>> +       if (priv->otg_phy_mode == PHY_MODE_USB_DEVICE) {
>> +               regmap_update_bits(priv->regmap, USB_R0,
>> +                               USB_R0_U2D_ACT, USB_R0_U2D_ACT);
>> +               regmap_update_bits(priv->regmap, USB_R0,
>> +                               USB_R0_U2D_SS_SCALEDOWN_MODE_MASK, 0);
>> +               regmap_update_bits(priv->regmap, USB_R4,
>> +                               USB_R4_P21_SLEEP_M0, USB_R4_P21_SLEEP_M0);
>> +       } else {
>> +               regmap_update_bits(priv->regmap, USB_R0,
>> +                               USB_R0_U2D_ACT, 0);
>> +               regmap_update_bits(priv->regmap, USB_R4,
>> +                               USB_R4_P21_SLEEP_M0, 0);
>> +       }
>> +}
> I was already confused by the name of this function in v1.
> do you think "dwc3_meson_g12a_usb_otg_apply_mode" is a suitable name?

Yep changed

> 
> [...]
>> +static int dwc3_meson_g12a_otg_mode_set(struct dwc3_meson_g12a *priv,
>> +                                       enum phy_mode mode)
>> +{
>> +       int ret;
>> +
>> +       if (!priv->phys[USB2_OTG_PHY])
>> +               return -EINVAL;
>> +
>> +       if (mode == PHY_MODE_USB_HOST)
>> +               dev_info(priv->dev, "switching to Host Mode\n");
>> +       else
>> +               dev_info(priv->dev, "switching to Device Mode\n");
>> +
>> +       if (priv->vbus) {
>> +               if (mode == PHY_MODE_USB_DEVICE)
>> +                       ret = regulator_disable(priv->vbus);
>> +               else
>> +                       ret = regulator_enable(priv->vbus);
> do we need to track the regulator status (whether it's enabled or not)?
> the regulator framework WARN()s if it detects "unbalanced disables for
> <regulator>"
> (I haven't tested this on one of my boards yet, so maybe it works
> because the callers of dwc3_meson_g12a_otg_mode_set() protect against
> this by not calling this function if the mode doesn't change)

I handled this case by enabling the regulator _before_, as we default in
Host/OTG mode in probe, then eventually switch to device.

In this case, we don't have to track the status, and further calls
to dwc3_meson_g12a_otg_mode_set() will only change the regulator
on mode change.

> 
>> +               if (ret)
>> +                       return ret;
>> +               }
>> +
>> +               priv->otg_phy_mode = mode;
>> +
>> +               dwc3_meson_g12a_usb2_set_mode(priv, USB2_OTG_PHY, mode);
>> +
>> +               dwc3_meson_g12a_usb_init_mode(priv);
>> +
>> +               return phy_set_mode(priv->phys[USB2_OTG_PHY], mode);
>> + }
> this is the only place where phy_set_mode is called
> I'm fine with keeping it but then it should be consistent at least for
> all USB2 PHYs.
> I suggest to either move the phy_set_mode call to
> dwc3_meson_g12a_usb2_set_mode or to remove it.

I will remove it, it's useless for now.

> 
> [...]
>> +static int dwc3_meson_g12a_role_set(struct device *dev, enum usb_role role)
>> +{
>> +       struct dwc3_meson_g12a *priv = dev_get_drvdata(dev);
>> +       enum phy_mode mode;
>> +
>> +       if (role == USB_ROLE_NONE)
>> +               return 0;
>> +
>> +       mode = role == USB_ROLE_HOST ? PHY_MODE_USB_HOST : PHY_MODE_USB_DEVICE;
> (without surrounding parens I find the "role == USB_ROLE_HOST" part
> hard to distinguish from the "mode =" operation. if more people think
> this way then please speak up - otherwise it's probably just my
> personal taste)

Yep, I added parenthesis and changed indentation to make it clearer.

> 
> [...]
>> +static struct device *dwc3_meson_g12_find_child(struct device *dev,
>> +                                               const char *compatible)
>> +{
>> +       struct platform_device *pdev;
>> +       struct device_node *np;
>> +
>> +       np = of_find_compatible_node(dev->of_node, NULL, compatible);
>> +       if (!np)
>> +               return NULL;
>> +
>> +       pdev = of_find_device_by_node(np);
> maybe switch to of_get_compatible_child() here? This was done for the
> MMC driver in c483a5cc9d09f4 ("mmc: meson-mx-sdio: fix OF child-node
> lookup"), but I'm not sure if the problem described there also applies
> to dwc3_meson_g12_find_child

of_get_compatible_child() is new to me, switching to it !

> 
> [...]
>> +static int dwc3_meson_g12a_probe(struct platform_device *pdev)
>> +{
>> +       struct dwc3_meson_g12a  *priv;
>> +       struct device           *dev = &pdev->dev;
>> +       struct device_node      *np = dev->of_node;
>> +       void __iomem *base;
>> +       struct resource *res;
>> +       enum phy_mode otg_id;
>> +       int ret, i;
>> +
>> +       priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
>> +       if (!priv)
>> +               return -ENOMEM;
>> +
>> +       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
>> +       base = devm_ioremap_resource(dev, res);
>> +       if (IS_ERR(base))
>> +               return PTR_ERR(base);
>> +
>> +       priv->regmap = devm_regmap_init_mmio(dev, base,
>> +                                            &phy_meson_g12a_usb3_regmap_conf);
>> +       if (IS_ERR(priv->regmap))
>> +               return PTR_ERR(priv->regmap);
>> +
>> +       priv->vbus = devm_regulator_get_optional(dev, "vbus");
>> +       if (IS_ERR(priv->vbus)) {
>> +               if (PTR_ERR(priv->vbus) == -EPROBE_DEFER)
>> +                       return PTR_ERR(priv->vbus);
>> +               priv->vbus = NULL;
>> +       }
>> +
>> +       priv->clk = devm_clk_get(dev, NULL);
>> +       if (IS_ERR(priv->clk))
>> +               return PTR_ERR(priv->clk);
>> +
>> +       ret = clk_prepare_enable(priv->clk);
>> +       if (ret)
>> +               return ret;
>> +
>> +       platform_set_drvdata(pdev, priv);
>> +       priv->dev = dev;
>> +
>> +       priv->reset = devm_reset_control_get(dev, NULL);
>> +       if (IS_ERR(priv->reset)) {
>> +               ret = PTR_ERR(priv->reset);
>> +               dev_err(dev, "failed to get device reset, err=%d\n", ret);
>> +               return ret;
>> +       }
> clk_prepare_enable is called a few lines above but this (and a few
> more) error-paths don't call clk_disable_unprepare.
> Jerome suggested in the dwmac-meson8b driver that I use something
> like, which will even allow you to drop the clk_disable_unprepare call
> from dwc3_meson_g12a_remove and catch all error cases in
> dwc3_meson_g12a_probe at the same time:
>   devm_add_action_or_reset(dev, (void(*)(void
> *))clk_disable_unprepare, priv->clk);
> (if you go with this then you also need to remove the
> clk_disable_unprepare after of_platform_populate)

Indeed I totally forgot this, thanks !

> 
> [...]
>> +static int dwc3_meson_g12a_remove(struct platform_device *pdev)
>> +{
>> +       struct dwc3_meson_g12a *priv = platform_get_drvdata(pdev);
>> +       struct device *dev = &pdev->dev;
>> +       int i;
>> +
>> +       usb_role_switch_unregister(priv->role_switch);
>> +
>> +       of_platform_depopulate(dev);
>> +
>> +       for (i = 0 ; i < PHY_COUNT ; ++i) {
>> +               phy_power_off(priv->phys[i]);
>> +               phy_exit(priv->phys[i]);
>> +               phy_put(priv->phys[i]);
>> +       }
>> +
>> +       clk_disable_unprepare(priv->clk);
>> +       clk_put(priv->clk);
> priv->clk is obtained with devm_clk_get so the common clock framework
> will call clk_put for us automatically

Right

> 
> [...]
>> +static int __maybe_unused dwc3_meson_g12a_suspend(struct device *dev)
>> +{
>> +       struct dwc3_meson_g12a *priv = dev_get_drvdata(dev);
>> +       int i;
>> +
>> +       for (i = 0 ; i < PHY_COUNT ; ++i)
>> +               if (priv->phys[i])
>> +                       phy_exit(priv->phys[i]);
> phy_init is NULL-safe, so you can drop the NULL-check above

Forgot this one


> 
>> +
>> +       reset_control_assert(priv->reset);
>> +
>> +       return 0;
>> +}
>> +
>> +static int __maybe_unused dwc3_meson_g12a_resume(struct device *dev)
>> +{
>> +       struct dwc3_meson_g12a *priv = dev_get_drvdata(dev);
>> +       int i, ret;
>> +
>> +       reset_control_deassert(priv->reset);
>> +
>> +       dwc3_meson_g12a_usb_init(priv);
>> +
>> +       /* Init PHYs */
>> +       for (i = 0 ; i < PHY_COUNT ; ++i) {
>> +               if (priv->phys[i]) {
>> +                       ret = phy_init(priv->phys[i]);
> phy_init is NULL-safe, so you can drop the NULL-check above

Good catch...

> 
> 
> Regards
> Martin
> 

Thanks !!

Neil

WARNING: multiple messages have this Message-ID (diff)
From: Neil Armstrong <narmstrong@baylibre.com>
To: Martin Blumenstingl <martin.blumenstingl@googlemail.com>
Cc: gregkh@linuxfoundation.org, hminas@synopsys.com,
	balbi@kernel.org, kishon@ti.com,
	linux-amlogic@lists.infradead.org, linux-usb@vger.kernel.org,
	linux-kernel@vger.kernel.org,
	linux-arm-kernel@lists.infradead.org
Subject: [v2,8/8] usb: dwc3: Add Amlogic G12A DWC3 glue
Date: Wed, 13 Mar 2019 14:07:34 +0100	[thread overview]
Message-ID: <6f84d21f-1093-185f-dd70-b470bfa9c7da@baylibre.com> (raw)

On 11/03/2019 22:56, Martin Blumenstingl wrote:
> Hi Neil,
> 
> On Mon, Mar 4, 2019 at 11:41 AM Neil Armstrong <narmstrong@baylibre.com> wrote:
> [...]
>> +static void dwc3_meson_g12a_usb_init_mode(struct dwc3_meson_g12a *priv)
>> +{
>> +       if (priv->otg_phy_mode == PHY_MODE_USB_DEVICE) {
>> +               regmap_update_bits(priv->regmap, USB_R0,
>> +                               USB_R0_U2D_ACT, USB_R0_U2D_ACT);
>> +               regmap_update_bits(priv->regmap, USB_R0,
>> +                               USB_R0_U2D_SS_SCALEDOWN_MODE_MASK, 0);
>> +               regmap_update_bits(priv->regmap, USB_R4,
>> +                               USB_R4_P21_SLEEP_M0, USB_R4_P21_SLEEP_M0);
>> +       } else {
>> +               regmap_update_bits(priv->regmap, USB_R0,
>> +                               USB_R0_U2D_ACT, 0);
>> +               regmap_update_bits(priv->regmap, USB_R4,
>> +                               USB_R4_P21_SLEEP_M0, 0);
>> +       }
>> +}
> I was already confused by the name of this function in v1.
> do you think "dwc3_meson_g12a_usb_otg_apply_mode" is a suitable name?

Yep changed

> 
> [...]
>> +static int dwc3_meson_g12a_otg_mode_set(struct dwc3_meson_g12a *priv,
>> +                                       enum phy_mode mode)
>> +{
>> +       int ret;
>> +
>> +       if (!priv->phys[USB2_OTG_PHY])
>> +               return -EINVAL;
>> +
>> +       if (mode == PHY_MODE_USB_HOST)
>> +               dev_info(priv->dev, "switching to Host Mode\n");
>> +       else
>> +               dev_info(priv->dev, "switching to Device Mode\n");
>> +
>> +       if (priv->vbus) {
>> +               if (mode == PHY_MODE_USB_DEVICE)
>> +                       ret = regulator_disable(priv->vbus);
>> +               else
>> +                       ret = regulator_enable(priv->vbus);
> do we need to track the regulator status (whether it's enabled or not)?
> the regulator framework WARN()s if it detects "unbalanced disables for
> <regulator>"
> (I haven't tested this on one of my boards yet, so maybe it works
> because the callers of dwc3_meson_g12a_otg_mode_set() protect against
> this by not calling this function if the mode doesn't change)

I handled this case by enabling the regulator _before_, as we default in
Host/OTG mode in probe, then eventually switch to device.

In this case, we don't have to track the status, and further calls
to dwc3_meson_g12a_otg_mode_set() will only change the regulator
on mode change.

> 
>> +               if (ret)
>> +                       return ret;
>> +               }
>> +
>> +               priv->otg_phy_mode = mode;
>> +
>> +               dwc3_meson_g12a_usb2_set_mode(priv, USB2_OTG_PHY, mode);
>> +
>> +               dwc3_meson_g12a_usb_init_mode(priv);
>> +
>> +               return phy_set_mode(priv->phys[USB2_OTG_PHY], mode);
>> + }
> this is the only place where phy_set_mode is called
> I'm fine with keeping it but then it should be consistent at least for
> all USB2 PHYs.
> I suggest to either move the phy_set_mode call to
> dwc3_meson_g12a_usb2_set_mode or to remove it.

I will remove it, it's useless for now.

> 
> [...]
>> +static int dwc3_meson_g12a_role_set(struct device *dev, enum usb_role role)
>> +{
>> +       struct dwc3_meson_g12a *priv = dev_get_drvdata(dev);
>> +       enum phy_mode mode;
>> +
>> +       if (role == USB_ROLE_NONE)
>> +               return 0;
>> +
>> +       mode = role == USB_ROLE_HOST ? PHY_MODE_USB_HOST : PHY_MODE_USB_DEVICE;
> (without surrounding parens I find the "role == USB_ROLE_HOST" part
> hard to distinguish from the "mode =" operation. if more people think
> this way then please speak up - otherwise it's probably just my
> personal taste)

Yep, I added parenthesis and changed indentation to make it clearer.

> 
> [...]
>> +static struct device *dwc3_meson_g12_find_child(struct device *dev,
>> +                                               const char *compatible)
>> +{
>> +       struct platform_device *pdev;
>> +       struct device_node *np;
>> +
>> +       np = of_find_compatible_node(dev->of_node, NULL, compatible);
>> +       if (!np)
>> +               return NULL;
>> +
>> +       pdev = of_find_device_by_node(np);
> maybe switch to of_get_compatible_child() here? This was done for the
> MMC driver in c483a5cc9d09f4 ("mmc: meson-mx-sdio: fix OF child-node
> lookup"), but I'm not sure if the problem described there also applies
> to dwc3_meson_g12_find_child

of_get_compatible_child() is new to me, switching to it !

> 
> [...]
>> +static int dwc3_meson_g12a_probe(struct platform_device *pdev)
>> +{
>> +       struct dwc3_meson_g12a  *priv;
>> +       struct device           *dev = &pdev->dev;
>> +       struct device_node      *np = dev->of_node;
>> +       void __iomem *base;
>> +       struct resource *res;
>> +       enum phy_mode otg_id;
>> +       int ret, i;
>> +
>> +       priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
>> +       if (!priv)
>> +               return -ENOMEM;
>> +
>> +       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
>> +       base = devm_ioremap_resource(dev, res);
>> +       if (IS_ERR(base))
>> +               return PTR_ERR(base);
>> +
>> +       priv->regmap = devm_regmap_init_mmio(dev, base,
>> +                                            &phy_meson_g12a_usb3_regmap_conf);
>> +       if (IS_ERR(priv->regmap))
>> +               return PTR_ERR(priv->regmap);
>> +
>> +       priv->vbus = devm_regulator_get_optional(dev, "vbus");
>> +       if (IS_ERR(priv->vbus)) {
>> +               if (PTR_ERR(priv->vbus) == -EPROBE_DEFER)
>> +                       return PTR_ERR(priv->vbus);
>> +               priv->vbus = NULL;
>> +       }
>> +
>> +       priv->clk = devm_clk_get(dev, NULL);
>> +       if (IS_ERR(priv->clk))
>> +               return PTR_ERR(priv->clk);
>> +
>> +       ret = clk_prepare_enable(priv->clk);
>> +       if (ret)
>> +               return ret;
>> +
>> +       platform_set_drvdata(pdev, priv);
>> +       priv->dev = dev;
>> +
>> +       priv->reset = devm_reset_control_get(dev, NULL);
>> +       if (IS_ERR(priv->reset)) {
>> +               ret = PTR_ERR(priv->reset);
>> +               dev_err(dev, "failed to get device reset, err=%d\n", ret);
>> +               return ret;
>> +       }
> clk_prepare_enable is called a few lines above but this (and a few
> more) error-paths don't call clk_disable_unprepare.
> Jerome suggested in the dwmac-meson8b driver that I use something
> like, which will even allow you to drop the clk_disable_unprepare call
> from dwc3_meson_g12a_remove and catch all error cases in
> dwc3_meson_g12a_probe at the same time:
>   devm_add_action_or_reset(dev, (void(*)(void
> *))clk_disable_unprepare, priv->clk);
> (if you go with this then you also need to remove the
> clk_disable_unprepare after of_platform_populate)

Indeed I totally forgot this, thanks !

> 
> [...]
>> +static int dwc3_meson_g12a_remove(struct platform_device *pdev)
>> +{
>> +       struct dwc3_meson_g12a *priv = platform_get_drvdata(pdev);
>> +       struct device *dev = &pdev->dev;
>> +       int i;
>> +
>> +       usb_role_switch_unregister(priv->role_switch);
>> +
>> +       of_platform_depopulate(dev);
>> +
>> +       for (i = 0 ; i < PHY_COUNT ; ++i) {
>> +               phy_power_off(priv->phys[i]);
>> +               phy_exit(priv->phys[i]);
>> +               phy_put(priv->phys[i]);
>> +       }
>> +
>> +       clk_disable_unprepare(priv->clk);
>> +       clk_put(priv->clk);
> priv->clk is obtained with devm_clk_get so the common clock framework
> will call clk_put for us automatically

Right

> 
> [...]
>> +static int __maybe_unused dwc3_meson_g12a_suspend(struct device *dev)
>> +{
>> +       struct dwc3_meson_g12a *priv = dev_get_drvdata(dev);
>> +       int i;
>> +
>> +       for (i = 0 ; i < PHY_COUNT ; ++i)
>> +               if (priv->phys[i])
>> +                       phy_exit(priv->phys[i]);
> phy_init is NULL-safe, so you can drop the NULL-check above

Forgot this one


> 
>> +
>> +       reset_control_assert(priv->reset);
>> +
>> +       return 0;
>> +}
>> +
>> +static int __maybe_unused dwc3_meson_g12a_resume(struct device *dev)
>> +{
>> +       struct dwc3_meson_g12a *priv = dev_get_drvdata(dev);
>> +       int i, ret;
>> +
>> +       reset_control_deassert(priv->reset);
>> +
>> +       dwc3_meson_g12a_usb_init(priv);
>> +
>> +       /* Init PHYs */
>> +       for (i = 0 ; i < PHY_COUNT ; ++i) {
>> +               if (priv->phys[i]) {
>> +                       ret = phy_init(priv->phys[i]);
> phy_init is NULL-safe, so you can drop the NULL-check above

Good catch...

> 
> 
> Regards
> Martin
> 

Thanks !!

Neil

WARNING: multiple messages have this Message-ID (diff)
From: Neil Armstrong <narmstrong@baylibre.com>
To: Martin Blumenstingl <martin.blumenstingl@googlemail.com>
Cc: balbi@kernel.org, gregkh@linuxfoundation.org,
	linux-usb@vger.kernel.org, linux-kernel@vger.kernel.org,
	kishon@ti.com, hminas@synopsys.com,
	linux-amlogic@lists.infradead.org,
	linux-arm-kernel@lists.infradead.org
Subject: Re: [PATCH v2 8/8] usb: dwc3: Add Amlogic G12A DWC3 glue
Date: Wed, 13 Mar 2019 14:07:34 +0100	[thread overview]
Message-ID: <6f84d21f-1093-185f-dd70-b470bfa9c7da@baylibre.com> (raw)
In-Reply-To: <CAFBinCAWEEKdsG2ZGCsFd1XyTUerAJpxJFEGGF-6j3UmpOmc=Q@mail.gmail.com>

On 11/03/2019 22:56, Martin Blumenstingl wrote:
> Hi Neil,
> 
> On Mon, Mar 4, 2019 at 11:41 AM Neil Armstrong <narmstrong@baylibre.com> wrote:
> [...]
>> +static void dwc3_meson_g12a_usb_init_mode(struct dwc3_meson_g12a *priv)
>> +{
>> +       if (priv->otg_phy_mode == PHY_MODE_USB_DEVICE) {
>> +               regmap_update_bits(priv->regmap, USB_R0,
>> +                               USB_R0_U2D_ACT, USB_R0_U2D_ACT);
>> +               regmap_update_bits(priv->regmap, USB_R0,
>> +                               USB_R0_U2D_SS_SCALEDOWN_MODE_MASK, 0);
>> +               regmap_update_bits(priv->regmap, USB_R4,
>> +                               USB_R4_P21_SLEEP_M0, USB_R4_P21_SLEEP_M0);
>> +       } else {
>> +               regmap_update_bits(priv->regmap, USB_R0,
>> +                               USB_R0_U2D_ACT, 0);
>> +               regmap_update_bits(priv->regmap, USB_R4,
>> +                               USB_R4_P21_SLEEP_M0, 0);
>> +       }
>> +}
> I was already confused by the name of this function in v1.
> do you think "dwc3_meson_g12a_usb_otg_apply_mode" is a suitable name?

Yep changed

> 
> [...]
>> +static int dwc3_meson_g12a_otg_mode_set(struct dwc3_meson_g12a *priv,
>> +                                       enum phy_mode mode)
>> +{
>> +       int ret;
>> +
>> +       if (!priv->phys[USB2_OTG_PHY])
>> +               return -EINVAL;
>> +
>> +       if (mode == PHY_MODE_USB_HOST)
>> +               dev_info(priv->dev, "switching to Host Mode\n");
>> +       else
>> +               dev_info(priv->dev, "switching to Device Mode\n");
>> +
>> +       if (priv->vbus) {
>> +               if (mode == PHY_MODE_USB_DEVICE)
>> +                       ret = regulator_disable(priv->vbus);
>> +               else
>> +                       ret = regulator_enable(priv->vbus);
> do we need to track the regulator status (whether it's enabled or not)?
> the regulator framework WARN()s if it detects "unbalanced disables for
> <regulator>"
> (I haven't tested this on one of my boards yet, so maybe it works
> because the callers of dwc3_meson_g12a_otg_mode_set() protect against
> this by not calling this function if the mode doesn't change)

I handled this case by enabling the regulator _before_, as we default in
Host/OTG mode in probe, then eventually switch to device.

In this case, we don't have to track the status, and further calls
to dwc3_meson_g12a_otg_mode_set() will only change the regulator
on mode change.

> 
>> +               if (ret)
>> +                       return ret;
>> +               }
>> +
>> +               priv->otg_phy_mode = mode;
>> +
>> +               dwc3_meson_g12a_usb2_set_mode(priv, USB2_OTG_PHY, mode);
>> +
>> +               dwc3_meson_g12a_usb_init_mode(priv);
>> +
>> +               return phy_set_mode(priv->phys[USB2_OTG_PHY], mode);
>> + }
> this is the only place where phy_set_mode is called
> I'm fine with keeping it but then it should be consistent at least for
> all USB2 PHYs.
> I suggest to either move the phy_set_mode call to
> dwc3_meson_g12a_usb2_set_mode or to remove it.

I will remove it, it's useless for now.

> 
> [...]
>> +static int dwc3_meson_g12a_role_set(struct device *dev, enum usb_role role)
>> +{
>> +       struct dwc3_meson_g12a *priv = dev_get_drvdata(dev);
>> +       enum phy_mode mode;
>> +
>> +       if (role == USB_ROLE_NONE)
>> +               return 0;
>> +
>> +       mode = role == USB_ROLE_HOST ? PHY_MODE_USB_HOST : PHY_MODE_USB_DEVICE;
> (without surrounding parens I find the "role == USB_ROLE_HOST" part
> hard to distinguish from the "mode =" operation. if more people think
> this way then please speak up - otherwise it's probably just my
> personal taste)

Yep, I added parenthesis and changed indentation to make it clearer.

> 
> [...]
>> +static struct device *dwc3_meson_g12_find_child(struct device *dev,
>> +                                               const char *compatible)
>> +{
>> +       struct platform_device *pdev;
>> +       struct device_node *np;
>> +
>> +       np = of_find_compatible_node(dev->of_node, NULL, compatible);
>> +       if (!np)
>> +               return NULL;
>> +
>> +       pdev = of_find_device_by_node(np);
> maybe switch to of_get_compatible_child() here? This was done for the
> MMC driver in c483a5cc9d09f4 ("mmc: meson-mx-sdio: fix OF child-node
> lookup"), but I'm not sure if the problem described there also applies
> to dwc3_meson_g12_find_child

of_get_compatible_child() is new to me, switching to it !

> 
> [...]
>> +static int dwc3_meson_g12a_probe(struct platform_device *pdev)
>> +{
>> +       struct dwc3_meson_g12a  *priv;
>> +       struct device           *dev = &pdev->dev;
>> +       struct device_node      *np = dev->of_node;
>> +       void __iomem *base;
>> +       struct resource *res;
>> +       enum phy_mode otg_id;
>> +       int ret, i;
>> +
>> +       priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
>> +       if (!priv)
>> +               return -ENOMEM;
>> +
>> +       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
>> +       base = devm_ioremap_resource(dev, res);
>> +       if (IS_ERR(base))
>> +               return PTR_ERR(base);
>> +
>> +       priv->regmap = devm_regmap_init_mmio(dev, base,
>> +                                            &phy_meson_g12a_usb3_regmap_conf);
>> +       if (IS_ERR(priv->regmap))
>> +               return PTR_ERR(priv->regmap);
>> +
>> +       priv->vbus = devm_regulator_get_optional(dev, "vbus");
>> +       if (IS_ERR(priv->vbus)) {
>> +               if (PTR_ERR(priv->vbus) == -EPROBE_DEFER)
>> +                       return PTR_ERR(priv->vbus);
>> +               priv->vbus = NULL;
>> +       }
>> +
>> +       priv->clk = devm_clk_get(dev, NULL);
>> +       if (IS_ERR(priv->clk))
>> +               return PTR_ERR(priv->clk);
>> +
>> +       ret = clk_prepare_enable(priv->clk);
>> +       if (ret)
>> +               return ret;
>> +
>> +       platform_set_drvdata(pdev, priv);
>> +       priv->dev = dev;
>> +
>> +       priv->reset = devm_reset_control_get(dev, NULL);
>> +       if (IS_ERR(priv->reset)) {
>> +               ret = PTR_ERR(priv->reset);
>> +               dev_err(dev, "failed to get device reset, err=%d\n", ret);
>> +               return ret;
>> +       }
> clk_prepare_enable is called a few lines above but this (and a few
> more) error-paths don't call clk_disable_unprepare.
> Jerome suggested in the dwmac-meson8b driver that I use something
> like, which will even allow you to drop the clk_disable_unprepare call
> from dwc3_meson_g12a_remove and catch all error cases in
> dwc3_meson_g12a_probe at the same time:
>   devm_add_action_or_reset(dev, (void(*)(void
> *))clk_disable_unprepare, priv->clk);
> (if you go with this then you also need to remove the
> clk_disable_unprepare after of_platform_populate)

Indeed I totally forgot this, thanks !

> 
> [...]
>> +static int dwc3_meson_g12a_remove(struct platform_device *pdev)
>> +{
>> +       struct dwc3_meson_g12a *priv = platform_get_drvdata(pdev);
>> +       struct device *dev = &pdev->dev;
>> +       int i;
>> +
>> +       usb_role_switch_unregister(priv->role_switch);
>> +
>> +       of_platform_depopulate(dev);
>> +
>> +       for (i = 0 ; i < PHY_COUNT ; ++i) {
>> +               phy_power_off(priv->phys[i]);
>> +               phy_exit(priv->phys[i]);
>> +               phy_put(priv->phys[i]);
>> +       }
>> +
>> +       clk_disable_unprepare(priv->clk);
>> +       clk_put(priv->clk);
> priv->clk is obtained with devm_clk_get so the common clock framework
> will call clk_put for us automatically

Right

> 
> [...]
>> +static int __maybe_unused dwc3_meson_g12a_suspend(struct device *dev)
>> +{
>> +       struct dwc3_meson_g12a *priv = dev_get_drvdata(dev);
>> +       int i;
>> +
>> +       for (i = 0 ; i < PHY_COUNT ; ++i)
>> +               if (priv->phys[i])
>> +                       phy_exit(priv->phys[i]);
> phy_init is NULL-safe, so you can drop the NULL-check above

Forgot this one


> 
>> +
>> +       reset_control_assert(priv->reset);
>> +
>> +       return 0;
>> +}
>> +
>> +static int __maybe_unused dwc3_meson_g12a_resume(struct device *dev)
>> +{
>> +       struct dwc3_meson_g12a *priv = dev_get_drvdata(dev);
>> +       int i, ret;
>> +
>> +       reset_control_deassert(priv->reset);
>> +
>> +       dwc3_meson_g12a_usb_init(priv);
>> +
>> +       /* Init PHYs */
>> +       for (i = 0 ; i < PHY_COUNT ; ++i) {
>> +               if (priv->phys[i]) {
>> +                       ret = phy_init(priv->phys[i]);
> phy_init is NULL-safe, so you can drop the NULL-check above

Good catch...

> 
> 
> Regards
> Martin
> 

Thanks !!

Neil

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

WARNING: multiple messages have this Message-ID (diff)
From: Neil Armstrong <narmstrong@baylibre.com>
To: Martin Blumenstingl <martin.blumenstingl@googlemail.com>
Cc: balbi@kernel.org, gregkh@linuxfoundation.org,
	linux-usb@vger.kernel.org, linux-kernel@vger.kernel.org,
	kishon@ti.com, hminas@synopsys.com,
	linux-amlogic@lists.infradead.org,
	linux-arm-kernel@lists.infradead.org
Subject: Re: [PATCH v2 8/8] usb: dwc3: Add Amlogic G12A DWC3 glue
Date: Wed, 13 Mar 2019 14:07:34 +0100	[thread overview]
Message-ID: <6f84d21f-1093-185f-dd70-b470bfa9c7da@baylibre.com> (raw)
In-Reply-To: <CAFBinCAWEEKdsG2ZGCsFd1XyTUerAJpxJFEGGF-6j3UmpOmc=Q@mail.gmail.com>

On 11/03/2019 22:56, Martin Blumenstingl wrote:
> Hi Neil,
> 
> On Mon, Mar 4, 2019 at 11:41 AM Neil Armstrong <narmstrong@baylibre.com> wrote:
> [...]
>> +static void dwc3_meson_g12a_usb_init_mode(struct dwc3_meson_g12a *priv)
>> +{
>> +       if (priv->otg_phy_mode == PHY_MODE_USB_DEVICE) {
>> +               regmap_update_bits(priv->regmap, USB_R0,
>> +                               USB_R0_U2D_ACT, USB_R0_U2D_ACT);
>> +               regmap_update_bits(priv->regmap, USB_R0,
>> +                               USB_R0_U2D_SS_SCALEDOWN_MODE_MASK, 0);
>> +               regmap_update_bits(priv->regmap, USB_R4,
>> +                               USB_R4_P21_SLEEP_M0, USB_R4_P21_SLEEP_M0);
>> +       } else {
>> +               regmap_update_bits(priv->regmap, USB_R0,
>> +                               USB_R0_U2D_ACT, 0);
>> +               regmap_update_bits(priv->regmap, USB_R4,
>> +                               USB_R4_P21_SLEEP_M0, 0);
>> +       }
>> +}
> I was already confused by the name of this function in v1.
> do you think "dwc3_meson_g12a_usb_otg_apply_mode" is a suitable name?

Yep changed

> 
> [...]
>> +static int dwc3_meson_g12a_otg_mode_set(struct dwc3_meson_g12a *priv,
>> +                                       enum phy_mode mode)
>> +{
>> +       int ret;
>> +
>> +       if (!priv->phys[USB2_OTG_PHY])
>> +               return -EINVAL;
>> +
>> +       if (mode == PHY_MODE_USB_HOST)
>> +               dev_info(priv->dev, "switching to Host Mode\n");
>> +       else
>> +               dev_info(priv->dev, "switching to Device Mode\n");
>> +
>> +       if (priv->vbus) {
>> +               if (mode == PHY_MODE_USB_DEVICE)
>> +                       ret = regulator_disable(priv->vbus);
>> +               else
>> +                       ret = regulator_enable(priv->vbus);
> do we need to track the regulator status (whether it's enabled or not)?
> the regulator framework WARN()s if it detects "unbalanced disables for
> <regulator>"
> (I haven't tested this on one of my boards yet, so maybe it works
> because the callers of dwc3_meson_g12a_otg_mode_set() protect against
> this by not calling this function if the mode doesn't change)

I handled this case by enabling the regulator _before_, as we default in
Host/OTG mode in probe, then eventually switch to device.

In this case, we don't have to track the status, and further calls
to dwc3_meson_g12a_otg_mode_set() will only change the regulator
on mode change.

> 
>> +               if (ret)
>> +                       return ret;
>> +               }
>> +
>> +               priv->otg_phy_mode = mode;
>> +
>> +               dwc3_meson_g12a_usb2_set_mode(priv, USB2_OTG_PHY, mode);
>> +
>> +               dwc3_meson_g12a_usb_init_mode(priv);
>> +
>> +               return phy_set_mode(priv->phys[USB2_OTG_PHY], mode);
>> + }
> this is the only place where phy_set_mode is called
> I'm fine with keeping it but then it should be consistent at least for
> all USB2 PHYs.
> I suggest to either move the phy_set_mode call to
> dwc3_meson_g12a_usb2_set_mode or to remove it.

I will remove it, it's useless for now.

> 
> [...]
>> +static int dwc3_meson_g12a_role_set(struct device *dev, enum usb_role role)
>> +{
>> +       struct dwc3_meson_g12a *priv = dev_get_drvdata(dev);
>> +       enum phy_mode mode;
>> +
>> +       if (role == USB_ROLE_NONE)
>> +               return 0;
>> +
>> +       mode = role == USB_ROLE_HOST ? PHY_MODE_USB_HOST : PHY_MODE_USB_DEVICE;
> (without surrounding parens I find the "role == USB_ROLE_HOST" part
> hard to distinguish from the "mode =" operation. if more people think
> this way then please speak up - otherwise it's probably just my
> personal taste)

Yep, I added parenthesis and changed indentation to make it clearer.

> 
> [...]
>> +static struct device *dwc3_meson_g12_find_child(struct device *dev,
>> +                                               const char *compatible)
>> +{
>> +       struct platform_device *pdev;
>> +       struct device_node *np;
>> +
>> +       np = of_find_compatible_node(dev->of_node, NULL, compatible);
>> +       if (!np)
>> +               return NULL;
>> +
>> +       pdev = of_find_device_by_node(np);
> maybe switch to of_get_compatible_child() here? This was done for the
> MMC driver in c483a5cc9d09f4 ("mmc: meson-mx-sdio: fix OF child-node
> lookup"), but I'm not sure if the problem described there also applies
> to dwc3_meson_g12_find_child

of_get_compatible_child() is new to me, switching to it !

> 
> [...]
>> +static int dwc3_meson_g12a_probe(struct platform_device *pdev)
>> +{
>> +       struct dwc3_meson_g12a  *priv;
>> +       struct device           *dev = &pdev->dev;
>> +       struct device_node      *np = dev->of_node;
>> +       void __iomem *base;
>> +       struct resource *res;
>> +       enum phy_mode otg_id;
>> +       int ret, i;
>> +
>> +       priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
>> +       if (!priv)
>> +               return -ENOMEM;
>> +
>> +       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
>> +       base = devm_ioremap_resource(dev, res);
>> +       if (IS_ERR(base))
>> +               return PTR_ERR(base);
>> +
>> +       priv->regmap = devm_regmap_init_mmio(dev, base,
>> +                                            &phy_meson_g12a_usb3_regmap_conf);
>> +       if (IS_ERR(priv->regmap))
>> +               return PTR_ERR(priv->regmap);
>> +
>> +       priv->vbus = devm_regulator_get_optional(dev, "vbus");
>> +       if (IS_ERR(priv->vbus)) {
>> +               if (PTR_ERR(priv->vbus) == -EPROBE_DEFER)
>> +                       return PTR_ERR(priv->vbus);
>> +               priv->vbus = NULL;
>> +       }
>> +
>> +       priv->clk = devm_clk_get(dev, NULL);
>> +       if (IS_ERR(priv->clk))
>> +               return PTR_ERR(priv->clk);
>> +
>> +       ret = clk_prepare_enable(priv->clk);
>> +       if (ret)
>> +               return ret;
>> +
>> +       platform_set_drvdata(pdev, priv);
>> +       priv->dev = dev;
>> +
>> +       priv->reset = devm_reset_control_get(dev, NULL);
>> +       if (IS_ERR(priv->reset)) {
>> +               ret = PTR_ERR(priv->reset);
>> +               dev_err(dev, "failed to get device reset, err=%d\n", ret);
>> +               return ret;
>> +       }
> clk_prepare_enable is called a few lines above but this (and a few
> more) error-paths don't call clk_disable_unprepare.
> Jerome suggested in the dwmac-meson8b driver that I use something
> like, which will even allow you to drop the clk_disable_unprepare call
> from dwc3_meson_g12a_remove and catch all error cases in
> dwc3_meson_g12a_probe at the same time:
>   devm_add_action_or_reset(dev, (void(*)(void
> *))clk_disable_unprepare, priv->clk);
> (if you go with this then you also need to remove the
> clk_disable_unprepare after of_platform_populate)

Indeed I totally forgot this, thanks !

> 
> [...]
>> +static int dwc3_meson_g12a_remove(struct platform_device *pdev)
>> +{
>> +       struct dwc3_meson_g12a *priv = platform_get_drvdata(pdev);
>> +       struct device *dev = &pdev->dev;
>> +       int i;
>> +
>> +       usb_role_switch_unregister(priv->role_switch);
>> +
>> +       of_platform_depopulate(dev);
>> +
>> +       for (i = 0 ; i < PHY_COUNT ; ++i) {
>> +               phy_power_off(priv->phys[i]);
>> +               phy_exit(priv->phys[i]);
>> +               phy_put(priv->phys[i]);
>> +       }
>> +
>> +       clk_disable_unprepare(priv->clk);
>> +       clk_put(priv->clk);
> priv->clk is obtained with devm_clk_get so the common clock framework
> will call clk_put for us automatically

Right

> 
> [...]
>> +static int __maybe_unused dwc3_meson_g12a_suspend(struct device *dev)
>> +{
>> +       struct dwc3_meson_g12a *priv = dev_get_drvdata(dev);
>> +       int i;
>> +
>> +       for (i = 0 ; i < PHY_COUNT ; ++i)
>> +               if (priv->phys[i])
>> +                       phy_exit(priv->phys[i]);
> phy_init is NULL-safe, so you can drop the NULL-check above

Forgot this one


> 
>> +
>> +       reset_control_assert(priv->reset);
>> +
>> +       return 0;
>> +}
>> +
>> +static int __maybe_unused dwc3_meson_g12a_resume(struct device *dev)
>> +{
>> +       struct dwc3_meson_g12a *priv = dev_get_drvdata(dev);
>> +       int i, ret;
>> +
>> +       reset_control_deassert(priv->reset);
>> +
>> +       dwc3_meson_g12a_usb_init(priv);
>> +
>> +       /* Init PHYs */
>> +       for (i = 0 ; i < PHY_COUNT ; ++i) {
>> +               if (priv->phys[i]) {
>> +                       ret = phy_init(priv->phys[i]);
> phy_init is NULL-safe, so you can drop the NULL-check above

Good catch...

> 
> 
> Regards
> Martin
> 

Thanks !!

Neil

_______________________________________________
linux-amlogic mailing list
linux-amlogic@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-amlogic

  reply	other threads:[~2019-03-13 13:07 UTC|newest]

Thread overview: 110+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-03-04 10:38 [PATCH v2 0/8] arm64: meson: Add support for USB on Amlogic G12A Neil Armstrong
2019-03-04 10:38 ` Neil Armstrong
2019-03-04 10:38 ` Neil Armstrong
2019-03-04 10:38 ` [PATCH v2 1/8] dt-bindings: phy: Add Amlogic G12A USB2 PHY Bindings Neil Armstrong
2019-03-04 10:38   ` Neil Armstrong
2019-03-04 10:38   ` Neil Armstrong
2019-03-04 10:38   ` [v2,1/8] " Neil Armstrong
2019-03-04 10:38 ` [PATCH v2 2/8] dt-bindings: phy: Add Amlogic G12A USB3+PCIE Combo " Neil Armstrong
2019-03-04 10:38   ` Neil Armstrong
2019-03-04 10:38   ` Neil Armstrong
2019-03-04 10:38   ` [v2,2/8] " Neil Armstrong
2019-03-04 10:38   ` [PATCH v2 2/8] " Neil Armstrong
2019-03-05 21:42   ` Martin Blumenstingl
2019-03-05 21:42     ` Martin Blumenstingl
2019-03-05 21:42     ` Martin Blumenstingl
2019-03-05 21:42     ` [v2,2/8] " Martin Blumenstingl
2019-03-07  8:35     ` [PATCH v2 2/8] " Neil Armstrong
2019-03-07  8:35       ` Neil Armstrong
2019-03-07  8:35       ` Neil Armstrong
2019-03-07  8:35       ` [v2,2/8] " Neil Armstrong
2019-03-12 18:23   ` [PATCH v2 2/8] " Rob Herring
2019-03-12 18:23     ` Rob Herring
2019-03-12 18:23     ` Rob Herring
2019-03-12 18:23     ` [v2,2/8] " Rob Herring
2019-03-12 18:23     ` [PATCH v2 2/8] " Rob Herring
2019-03-04 10:38 ` [PATCH v2 3/8] dt-bindings: usb: dwc2: Add Amlogic G12A DWC2 Compatible Neil Armstrong
2019-03-04 10:38   ` Neil Armstrong
2019-03-04 10:38   ` Neil Armstrong
2019-03-04 10:38   ` [v2,3/8] " Neil Armstrong
2019-03-04 10:38 ` [PATCH v2 4/8] dt-bindings: usb: dwc3: Add Amlogic G12A DWC3 Glue Bindings Neil Armstrong
2019-03-04 10:38   ` Neil Armstrong
2019-03-04 10:38   ` Neil Armstrong
2019-03-04 10:38   ` [v2,4/8] " Neil Armstrong
2019-03-06 21:27   ` [PATCH v2 4/8] " Martin Blumenstingl
2019-03-06 21:27     ` Martin Blumenstingl
2019-03-06 21:27     ` Martin Blumenstingl
2019-03-06 21:27     ` [v2,4/8] " Martin Blumenstingl
2019-03-07  8:36     ` [PATCH v2 4/8] " Neil Armstrong
2019-03-07  8:36       ` Neil Armstrong
2019-03-07  8:36       ` Neil Armstrong
2019-03-07  8:36       ` [v2,4/8] " Neil Armstrong
2019-03-12 18:29   ` [PATCH v2 4/8] " Rob Herring
2019-03-12 18:29     ` Rob Herring
2019-03-12 18:29     ` Rob Herring
2019-03-12 18:29     ` [v2,4/8] " Rob Herring
2019-03-12 18:29     ` [PATCH v2 4/8] " Rob Herring
2019-03-04 10:38 ` [PATCH v2 5/8] phy: amlogic: add Amlogic G12A USB2 PHY Driver Neil Armstrong
2019-03-04 10:38   ` Neil Armstrong
2019-03-04 10:38   ` Neil Armstrong
2019-03-04 10:38   ` [v2,5/8] " Neil Armstrong
2019-03-06 21:00   ` [PATCH v2 5/8] " Martin Blumenstingl
2019-03-06 21:00     ` Martin Blumenstingl
2019-03-06 21:00     ` Martin Blumenstingl
2019-03-06 21:00     ` [v2,5/8] " Martin Blumenstingl
2019-03-07  8:41     ` [PATCH v2 5/8] " Neil Armstrong
2019-03-07  8:41       ` Neil Armstrong
2019-03-07  8:41       ` Neil Armstrong
2019-03-07  8:41       ` [v2,5/8] " Neil Armstrong
2019-03-11 21:04       ` [PATCH v2 5/8] " Martin Blumenstingl
2019-03-11 21:04         ` Martin Blumenstingl
2019-03-11 21:04         ` Martin Blumenstingl
2019-03-11 21:04         ` [v2,5/8] " Martin Blumenstingl
2019-03-04 10:38 ` [PATCH v2 6/8] phy: amlogic: Add Amlogic G12A USB3 + PCIE Combo " Neil Armstrong
2019-03-04 10:38   ` Neil Armstrong
2019-03-04 10:38   ` Neil Armstrong
2019-03-04 10:38   ` [v2,6/8] " Neil Armstrong
2019-03-06 21:04   ` [PATCH v2 6/8] " Martin Blumenstingl
2019-03-06 21:04     ` Martin Blumenstingl
2019-03-06 21:04     ` Martin Blumenstingl
2019-03-06 21:04     ` [v2,6/8] " Martin Blumenstingl
2019-03-07  8:44     ` [PATCH v2 6/8] " Neil Armstrong
2019-03-07  8:44       ` Neil Armstrong
2019-03-07  8:44       ` Neil Armstrong
2019-03-07  8:44       ` [v2,6/8] " Neil Armstrong
2019-03-11 21:14       ` [PATCH v2 6/8] " Martin Blumenstingl
2019-03-11 21:14         ` Martin Blumenstingl
2019-03-11 21:14         ` Martin Blumenstingl
2019-03-11 21:14         ` [v2,6/8] " Martin Blumenstingl
2019-03-04 10:38 ` [PATCH v2 7/8] usb: dwc2: Add Amlogic G12A DWC2 Params Neil Armstrong
2019-03-04 10:38   ` Neil Armstrong
2019-03-04 10:38   ` Neil Armstrong
2019-03-04 10:38   ` [v2,7/8] " Neil Armstrong
2019-03-04 10:38 ` [PATCH v2 8/8] usb: dwc3: Add Amlogic G12A DWC3 glue Neil Armstrong
2019-03-04 10:38   ` Neil Armstrong
2019-03-04 10:38   ` Neil Armstrong
2019-03-04 10:38   ` [v2,8/8] " Neil Armstrong
2019-03-07  2:02   ` [PATCH v2 8/8] " Chunfeng Yun
2019-03-07  2:02     ` Chunfeng Yun
2019-03-07  2:02     ` Chunfeng Yun
2019-03-07  2:02     ` [v2,8/8] " Chunfeng Yun
2019-03-07  9:45     ` [PATCH v2 8/8] " Neil Armstrong
2019-03-07  9:45       ` Neil Armstrong
2019-03-07  9:45       ` Neil Armstrong
2019-03-07  9:45       ` [v2,8/8] " Neil Armstrong
2019-03-07 11:01       ` [PATCH v2 8/8] " Chunfeng Yun
2019-03-07 11:01         ` Chunfeng Yun
2019-03-07 11:01         ` Chunfeng Yun
2019-03-07 11:01         ` [v2,8/8] " Chunfeng Yun
2019-03-11 21:19       ` [PATCH v2 8/8] " Martin Blumenstingl
2019-03-11 21:19         ` Martin Blumenstingl
2019-03-11 21:19         ` Martin Blumenstingl
2019-03-11 21:19         ` [v2,8/8] " Martin Blumenstingl
2019-03-11 21:56   ` [PATCH v2 8/8] " Martin Blumenstingl
2019-03-11 21:56     ` Martin Blumenstingl
2019-03-11 21:56     ` Martin Blumenstingl
2019-03-11 21:56     ` [v2,8/8] " Martin Blumenstingl
2019-03-13 13:07     ` Neil Armstrong [this message]
2019-03-13 13:07       ` [PATCH v2 8/8] " Neil Armstrong
2019-03-13 13:07       ` Neil Armstrong
2019-03-13 13:07       ` [v2,8/8] " Neil Armstrong

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=6f84d21f-1093-185f-dd70-b470bfa9c7da@baylibre.com \
    --to=narmstrong@baylibre.com \
    --cc=balbi@kernel.org \
    --cc=gregkh@linuxfoundation.org \
    --cc=hminas@synopsys.com \
    --cc=kishon@ti.com \
    --cc=linux-amlogic@lists.infradead.org \
    --cc=linux-arm-kernel@lists.infradead.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-usb@vger.kernel.org \
    --cc=martin.blumenstingl@googlemail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.