All of lore.kernel.org
 help / color / mirror / Atom feed
From: Chunfeng Yun <chunfeng.yun@mediatek.com>
To: Neil Armstrong <narmstrong@baylibre.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-arm-kernel@lists.infradead.org>,
	<linux-kernel@vger.kernel.org>
Subject: Re: [PATCH v2 8/8] usb: dwc3: Add Amlogic G12A DWC3 glue
Date: Thu, 7 Mar 2019 10:02:56 +0800	[thread overview]
Message-ID: <1551924176.2210.104.camel@mhfsdcap03> (raw)
In-Reply-To: <20190304103846.2060-9-narmstrong@baylibre.com>

Hi,
On Mon, 2019-03-04 at 11:38 +0100, Neil Armstrong wrote:
> Adds support for Amlogic G12A USB Control Glue HW.
> 
> The Amlogic G12A SoC Family embeds 2 USB Controllers :
> - a DWC3 IP configured as Host for USB2 and USB3
> - a DWC2 IP configured as Peripheral USB2 Only
> 
> A glue connects these both controllers to 2 USB2 PHYs, and optionnally
> to an USB3+PCIE Combo PHY shared with the PCIE controller.
> 
> The Glue configures the UTMI 8bit interfaces for the USB2 PHYs, including
> routing of the OTG PHY between the DWC3 and DWC2 controllers, and
> setups the on-chip OTG mode selection for this PHY.
> 
> This drivers supports the on-probe setup of the OTG mode, and manually
> via a debugfs interface. The IRQ mode change detect is yet to be added
> in a future patchset, mainly due to lack of hardware to validate on.
> 
> Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
> ---
>  drivers/usb/dwc3/Kconfig           |  10 +
>  drivers/usb/dwc3/Makefile          |   1 +
>  drivers/usb/dwc3/dwc3-meson-g12a.c | 601 +++++++++++++++++++++++++++++
>  3 files changed, 612 insertions(+)
>  create mode 100644 drivers/usb/dwc3/dwc3-meson-g12a.c
> 
> diff --git a/drivers/usb/dwc3/Kconfig b/drivers/usb/dwc3/Kconfig
> index 1a0404fda596..21ce7368d325 100644
> --- a/drivers/usb/dwc3/Kconfig
> +++ b/drivers/usb/dwc3/Kconfig
> @@ -93,6 +93,16 @@ config USB_DWC3_KEYSTONE
>  	  Support of USB2/3 functionality in TI Keystone2 platforms.
>  	  Say 'Y' or 'M' here if you have one such device
>  
> +config USB_DWC3_MESON_G12A
> +       tristate "Amlogic Meson G12A Platforms"
> +       depends on OF && COMMON_CLK
> +       depends on ARCH_MESON || COMPILE_TEST
> +       default USB_DWC3
> +       select USB_ROLE_SWITCH
> +       help
> +         Support USB2/3 functionality in Amlogic G12A platforms.
> +	 Say 'Y' or 'M' if you have one such device.
> +
>  config USB_DWC3_OF_SIMPLE
>         tristate "Generic OF Simple Glue Layer"
>         depends on OF && COMMON_CLK
> diff --git a/drivers/usb/dwc3/Makefile b/drivers/usb/dwc3/Makefile
> index 6e3ef6144e5d..ae86da0dc5bd 100644
> --- a/drivers/usb/dwc3/Makefile
> +++ b/drivers/usb/dwc3/Makefile
> @@ -47,6 +47,7 @@ obj-$(CONFIG_USB_DWC3_EXYNOS)		+= dwc3-exynos.o
>  obj-$(CONFIG_USB_DWC3_PCI)		+= dwc3-pci.o
>  obj-$(CONFIG_USB_DWC3_HAPS)		+= dwc3-haps.o
>  obj-$(CONFIG_USB_DWC3_KEYSTONE)		+= dwc3-keystone.o
> +obj-$(CONFIG_USB_DWC3_MESON_G12A)	+= dwc3-meson-g12a.o
>  obj-$(CONFIG_USB_DWC3_OF_SIMPLE)	+= dwc3-of-simple.o
>  obj-$(CONFIG_USB_DWC3_ST)		+= dwc3-st.o
>  obj-$(CONFIG_USB_DWC3_QCOM)		+= dwc3-qcom.o
> diff --git a/drivers/usb/dwc3/dwc3-meson-g12a.c b/drivers/usb/dwc3/dwc3-meson-g12a.c
> new file mode 100644
> index 000000000000..75942614a034
> --- /dev/null
> +++ b/drivers/usb/dwc3/dwc3-meson-g12a.c
> @@ -0,0 +1,601 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * USB Glue for Amlogic G12A SoCs
> + *
> + * Copyright (c) 2019 BayLibre, SAS
> + * Author: Neil Armstrong <narmstrong@baylibre.com>
> + */
> +
> +/*
> + * The USB is organized with a glue around the DWC3 Controller IP as :
> + * - Control registers for each USB2 Ports
> + * - Control registers for the USB PHY layer
> + * - SuperSpeed PHY can be enabled only if port is used
> + *
> + * TOFIX:
> + * - Add dynamic OTG switching with ID change interrupt
> + */
> +
[...]
> +
> +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;
> +	}
> +
> +	ret = reset_control_reset(priv->reset);
> +	if (ret)
> +		return ret;
> +
> +	ret = dwc3_meson_g12a_get_phys(priv);
> +	if (ret)
> +		return ret;
> +
> +	ret = regulator_enable(priv->vbus);
> +	if (ret)
> +		return ret;
> +
> +	/* Get dr_mode */
> +	priv->otg_mode = usb_get_dr_mode(dev);
> +
> +	dwc3_meson_g12a_usb_init(priv);
> +
> +	/* Set PHY Power */
> +	for (i = 0 ; i < PHY_COUNT ; ++i) {
> +		ret = phy_power_on(priv->phys[i]);
> +		if (ret)
> +			goto err_phys_put;
> +	}
> +
> +	/* Init PHYs */
> +	for (i = 0 ; i < PHY_COUNT ; ++i) {
> +		ret = phy_init(priv->phys[i]);
> +		if (ret)
> +			goto err_phys_power;
> +	}
usually phy_init() first

> +
> +	ret = of_platform_populate(np, NULL, NULL, dev);
> +	if (ret) {
> +		clk_disable_unprepare(priv->clk);
> +		clk_put(priv->clk);
> +
> +		goto err_phys_exit;
> +	}
> +
> +	/* Setup OTG mode corresponding to the ID pin */
> +	if (priv->otg_mode == USB_DR_MODE_OTG) {
> +		/* TOFIX Handle ID mode toggling via IRQ */
> +		otg_id = dwc3_meson_g12a_get_id(priv);
> +		if (otg_id != priv->otg_phy_mode) {
> +			if (dwc3_meson_g12a_otg_mode_set(priv, otg_id))
> +				dev_warn(dev, "Failed to switch OTG mode\n");
> +		}
> +	}
> +
> +	/* Setup role switcher */
> +	priv->switch_desc.usb2_port = dwc3_meson_g12_find_child(dev,
> +								"snps,dwc3");
> +	priv->switch_desc.udc = dwc3_meson_g12_find_child(dev, "snps,dwc2");
> +	priv->switch_desc.allow_userspace_control = true;
> +	priv->switch_desc.set = dwc3_meson_g12a_role_set;
> +	priv->switch_desc.get = dwc3_meson_g12a_role_get;
to me, use a local variable for switch_desc

> +
> +	priv->role_switch = usb_role_switch_register(dev, &priv->switch_desc);
> +	if (IS_ERR(priv->role_switch))
> +		dev_warn(dev, "Unable to register Role Switch\n");
> +
> +	pm_runtime_set_active(dev);
> +	pm_runtime_enable(dev);
> +	pm_runtime_get_sync(dev);
> +
> +	return 0;
> +
> +err_phys_exit:
> +	for (i = 0 ; i < PHY_COUNT ; ++i)
> +		phy_exit(priv->phys[i]);
> +
> +err_phys_power:
> +	for (i = 0 ; i < PHY_COUNT ; ++i)
> +		phy_power_off(priv->phys[i]);
> +
> +err_phys_put:
> +	for (i = 0 ; i < PHY_COUNT ; ++i)
> +		phy_put(priv->phys[i]);
> +
The phys are got by devm_phy_optional_get(), no need call phy_put()
> +	return ret;
> +}
> +
> +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]);
ditto
> +	}
> +
> +	clk_disable_unprepare(priv->clk);
> +	clk_put(priv->clk);
> +
> +	pm_runtime_disable(dev);
> +	pm_runtime_put_noidle(dev);
> +	pm_runtime_set_suspended(dev);
> +
> +	return 0;
> +}
> +
> +static int __maybe_unused dwc3_meson_g12a_runtime_suspend(struct device *dev)
> +{
> +	struct dwc3_meson_g12a	*priv = dev_get_drvdata(dev);
> +
> +	clk_disable(priv->clk);
> +
> +	return 0;
> +}
> +
> +static int __maybe_unused dwc3_meson_g12a_runtime_resume(struct device *dev)
> +{
> +	struct dwc3_meson_g12a	*priv = dev_get_drvdata(dev);
> +
> +	return clk_enable(priv->clk);
> +}
> +
> +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]);
> +
> +	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]);
> +			if (ret)
> +				return ret;
> +		}
> +	}
> +
> +	return 0;
> +}
> +
> +static const struct dev_pm_ops dwc3_meson_g12a_dev_pm_ops = {
> +	SET_SYSTEM_SLEEP_PM_OPS(dwc3_meson_g12a_suspend, dwc3_meson_g12a_resume)
> +	SET_RUNTIME_PM_OPS(dwc3_meson_g12a_runtime_suspend,
> +			dwc3_meson_g12a_runtime_resume, NULL)
> +};
> +
> +static const struct of_device_id dwc3_meson_g12a_match[] = {
> +	{ .compatible = "amlogic,meson-g12a-usb-ctrl" },
> +	{ /* Sentinel */ }
> +};
> +MODULE_DEVICE_TABLE(of, dwc3_meson_g12a_match);
> +
> +static struct platform_driver dwc3_meson_g12a_driver = {
> +	.probe		= dwc3_meson_g12a_probe,
> +	.remove		= dwc3_meson_g12a_remove,
> +	.driver		= {
> +		.name	= "dwc3-meson-g12a",
> +		.of_match_table = dwc3_meson_g12a_match,
> +		.pm	= &dwc3_meson_g12a_dev_pm_ops,
> +	},
> +};
> +
> +module_platform_driver(dwc3_meson_g12a_driver);
> +MODULE_LICENSE("GPL v2");
> +MODULE_DESCRIPTION("Amlogic Meson G12A USB Glue Layer");
> +MODULE_AUTHOR("Neil Armstrong <narmstrong@baylibre.com>");



WARNING: multiple messages have this Message-ID (diff)
From: Chunfeng Yun <chunfeng.yun@mediatek.com>
To: Neil Armstrong <narmstrong@baylibre.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-arm-kernel@lists.infradead.org,
	linux-kernel@vger.kernel.org
Subject: [v2,8/8] usb: dwc3: Add Amlogic G12A DWC3 glue
Date: Thu, 7 Mar 2019 10:02:56 +0800	[thread overview]
Message-ID: <1551924176.2210.104.camel@mhfsdcap03> (raw)

Hi,
On Mon, 2019-03-04 at 11:38 +0100, Neil Armstrong wrote:
> Adds support for Amlogic G12A USB Control Glue HW.
> 
> The Amlogic G12A SoC Family embeds 2 USB Controllers :
> - a DWC3 IP configured as Host for USB2 and USB3
> - a DWC2 IP configured as Peripheral USB2 Only
> 
> A glue connects these both controllers to 2 USB2 PHYs, and optionnally
> to an USB3+PCIE Combo PHY shared with the PCIE controller.
> 
> The Glue configures the UTMI 8bit interfaces for the USB2 PHYs, including
> routing of the OTG PHY between the DWC3 and DWC2 controllers, and
> setups the on-chip OTG mode selection for this PHY.
> 
> This drivers supports the on-probe setup of the OTG mode, and manually
> via a debugfs interface. The IRQ mode change detect is yet to be added
> in a future patchset, mainly due to lack of hardware to validate on.
> 
> Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
> ---
>  drivers/usb/dwc3/Kconfig           |  10 +
>  drivers/usb/dwc3/Makefile          |   1 +
>  drivers/usb/dwc3/dwc3-meson-g12a.c | 601 +++++++++++++++++++++++++++++
>  3 files changed, 612 insertions(+)
>  create mode 100644 drivers/usb/dwc3/dwc3-meson-g12a.c
> 
> diff --git a/drivers/usb/dwc3/Kconfig b/drivers/usb/dwc3/Kconfig
> index 1a0404fda596..21ce7368d325 100644
> --- a/drivers/usb/dwc3/Kconfig
> +++ b/drivers/usb/dwc3/Kconfig
> @@ -93,6 +93,16 @@ config USB_DWC3_KEYSTONE
>  	  Support of USB2/3 functionality in TI Keystone2 platforms.
>  	  Say 'Y' or 'M' here if you have one such device
>  
> +config USB_DWC3_MESON_G12A
> +       tristate "Amlogic Meson G12A Platforms"
> +       depends on OF && COMMON_CLK
> +       depends on ARCH_MESON || COMPILE_TEST
> +       default USB_DWC3
> +       select USB_ROLE_SWITCH
> +       help
> +         Support USB2/3 functionality in Amlogic G12A platforms.
> +	 Say 'Y' or 'M' if you have one such device.
> +
>  config USB_DWC3_OF_SIMPLE
>         tristate "Generic OF Simple Glue Layer"
>         depends on OF && COMMON_CLK
> diff --git a/drivers/usb/dwc3/Makefile b/drivers/usb/dwc3/Makefile
> index 6e3ef6144e5d..ae86da0dc5bd 100644
> --- a/drivers/usb/dwc3/Makefile
> +++ b/drivers/usb/dwc3/Makefile
> @@ -47,6 +47,7 @@ obj-$(CONFIG_USB_DWC3_EXYNOS)		+= dwc3-exynos.o
>  obj-$(CONFIG_USB_DWC3_PCI)		+= dwc3-pci.o
>  obj-$(CONFIG_USB_DWC3_HAPS)		+= dwc3-haps.o
>  obj-$(CONFIG_USB_DWC3_KEYSTONE)		+= dwc3-keystone.o
> +obj-$(CONFIG_USB_DWC3_MESON_G12A)	+= dwc3-meson-g12a.o
>  obj-$(CONFIG_USB_DWC3_OF_SIMPLE)	+= dwc3-of-simple.o
>  obj-$(CONFIG_USB_DWC3_ST)		+= dwc3-st.o
>  obj-$(CONFIG_USB_DWC3_QCOM)		+= dwc3-qcom.o
> diff --git a/drivers/usb/dwc3/dwc3-meson-g12a.c b/drivers/usb/dwc3/dwc3-meson-g12a.c
> new file mode 100644
> index 000000000000..75942614a034
> --- /dev/null
> +++ b/drivers/usb/dwc3/dwc3-meson-g12a.c
> @@ -0,0 +1,601 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * USB Glue for Amlogic G12A SoCs
> + *
> + * Copyright (c) 2019 BayLibre, SAS
> + * Author: Neil Armstrong <narmstrong@baylibre.com>
> + */
> +
> +/*
> + * The USB is organized with a glue around the DWC3 Controller IP as :
> + * - Control registers for each USB2 Ports
> + * - Control registers for the USB PHY layer
> + * - SuperSpeed PHY can be enabled only if port is used
> + *
> + * TOFIX:
> + * - Add dynamic OTG switching with ID change interrupt
> + */
> +
[...]
> +
> +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;
> +	}
> +
> +	ret = reset_control_reset(priv->reset);
> +	if (ret)
> +		return ret;
> +
> +	ret = dwc3_meson_g12a_get_phys(priv);
> +	if (ret)
> +		return ret;
> +
> +	ret = regulator_enable(priv->vbus);
> +	if (ret)
> +		return ret;
> +
> +	/* Get dr_mode */
> +	priv->otg_mode = usb_get_dr_mode(dev);
> +
> +	dwc3_meson_g12a_usb_init(priv);
> +
> +	/* Set PHY Power */
> +	for (i = 0 ; i < PHY_COUNT ; ++i) {
> +		ret = phy_power_on(priv->phys[i]);
> +		if (ret)
> +			goto err_phys_put;
> +	}
> +
> +	/* Init PHYs */
> +	for (i = 0 ; i < PHY_COUNT ; ++i) {
> +		ret = phy_init(priv->phys[i]);
> +		if (ret)
> +			goto err_phys_power;
> +	}
usually phy_init() first

> +
> +	ret = of_platform_populate(np, NULL, NULL, dev);
> +	if (ret) {
> +		clk_disable_unprepare(priv->clk);
> +		clk_put(priv->clk);
> +
> +		goto err_phys_exit;
> +	}
> +
> +	/* Setup OTG mode corresponding to the ID pin */
> +	if (priv->otg_mode == USB_DR_MODE_OTG) {
> +		/* TOFIX Handle ID mode toggling via IRQ */
> +		otg_id = dwc3_meson_g12a_get_id(priv);
> +		if (otg_id != priv->otg_phy_mode) {
> +			if (dwc3_meson_g12a_otg_mode_set(priv, otg_id))
> +				dev_warn(dev, "Failed to switch OTG mode\n");
> +		}
> +	}
> +
> +	/* Setup role switcher */
> +	priv->switch_desc.usb2_port = dwc3_meson_g12_find_child(dev,
> +								"snps,dwc3");
> +	priv->switch_desc.udc = dwc3_meson_g12_find_child(dev, "snps,dwc2");
> +	priv->switch_desc.allow_userspace_control = true;
> +	priv->switch_desc.set = dwc3_meson_g12a_role_set;
> +	priv->switch_desc.get = dwc3_meson_g12a_role_get;
to me, use a local variable for switch_desc

> +
> +	priv->role_switch = usb_role_switch_register(dev, &priv->switch_desc);
> +	if (IS_ERR(priv->role_switch))
> +		dev_warn(dev, "Unable to register Role Switch\n");
> +
> +	pm_runtime_set_active(dev);
> +	pm_runtime_enable(dev);
> +	pm_runtime_get_sync(dev);
> +
> +	return 0;
> +
> +err_phys_exit:
> +	for (i = 0 ; i < PHY_COUNT ; ++i)
> +		phy_exit(priv->phys[i]);
> +
> +err_phys_power:
> +	for (i = 0 ; i < PHY_COUNT ; ++i)
> +		phy_power_off(priv->phys[i]);
> +
> +err_phys_put:
> +	for (i = 0 ; i < PHY_COUNT ; ++i)
> +		phy_put(priv->phys[i]);
> +
The phys are got by devm_phy_optional_get(), no need call phy_put()
> +	return ret;
> +}
> +
> +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]);
ditto
> +	}
> +
> +	clk_disable_unprepare(priv->clk);
> +	clk_put(priv->clk);
> +
> +	pm_runtime_disable(dev);
> +	pm_runtime_put_noidle(dev);
> +	pm_runtime_set_suspended(dev);
> +
> +	return 0;
> +}
> +
> +static int __maybe_unused dwc3_meson_g12a_runtime_suspend(struct device *dev)
> +{
> +	struct dwc3_meson_g12a	*priv = dev_get_drvdata(dev);
> +
> +	clk_disable(priv->clk);
> +
> +	return 0;
> +}
> +
> +static int __maybe_unused dwc3_meson_g12a_runtime_resume(struct device *dev)
> +{
> +	struct dwc3_meson_g12a	*priv = dev_get_drvdata(dev);
> +
> +	return clk_enable(priv->clk);
> +}
> +
> +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]);
> +
> +	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]);
> +			if (ret)
> +				return ret;
> +		}
> +	}
> +
> +	return 0;
> +}
> +
> +static const struct dev_pm_ops dwc3_meson_g12a_dev_pm_ops = {
> +	SET_SYSTEM_SLEEP_PM_OPS(dwc3_meson_g12a_suspend, dwc3_meson_g12a_resume)
> +	SET_RUNTIME_PM_OPS(dwc3_meson_g12a_runtime_suspend,
> +			dwc3_meson_g12a_runtime_resume, NULL)
> +};
> +
> +static const struct of_device_id dwc3_meson_g12a_match[] = {
> +	{ .compatible = "amlogic,meson-g12a-usb-ctrl" },
> +	{ /* Sentinel */ }
> +};
> +MODULE_DEVICE_TABLE(of, dwc3_meson_g12a_match);
> +
> +static struct platform_driver dwc3_meson_g12a_driver = {
> +	.probe		= dwc3_meson_g12a_probe,
> +	.remove		= dwc3_meson_g12a_remove,
> +	.driver		= {
> +		.name	= "dwc3-meson-g12a",
> +		.of_match_table = dwc3_meson_g12a_match,
> +		.pm	= &dwc3_meson_g12a_dev_pm_ops,
> +	},
> +};
> +
> +module_platform_driver(dwc3_meson_g12a_driver);
> +MODULE_LICENSE("GPL v2");
> +MODULE_DESCRIPTION("Amlogic Meson G12A USB Glue Layer");
> +MODULE_AUTHOR("Neil Armstrong <narmstrong@baylibre.com>");

WARNING: multiple messages have this Message-ID (diff)
From: Chunfeng Yun <chunfeng.yun@mediatek.com>
To: Neil Armstrong <narmstrong@baylibre.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: Thu, 7 Mar 2019 10:02:56 +0800	[thread overview]
Message-ID: <1551924176.2210.104.camel@mhfsdcap03> (raw)
In-Reply-To: <20190304103846.2060-9-narmstrong@baylibre.com>

Hi,
On Mon, 2019-03-04 at 11:38 +0100, Neil Armstrong wrote:
> Adds support for Amlogic G12A USB Control Glue HW.
> 
> The Amlogic G12A SoC Family embeds 2 USB Controllers :
> - a DWC3 IP configured as Host for USB2 and USB3
> - a DWC2 IP configured as Peripheral USB2 Only
> 
> A glue connects these both controllers to 2 USB2 PHYs, and optionnally
> to an USB3+PCIE Combo PHY shared with the PCIE controller.
> 
> The Glue configures the UTMI 8bit interfaces for the USB2 PHYs, including
> routing of the OTG PHY between the DWC3 and DWC2 controllers, and
> setups the on-chip OTG mode selection for this PHY.
> 
> This drivers supports the on-probe setup of the OTG mode, and manually
> via a debugfs interface. The IRQ mode change detect is yet to be added
> in a future patchset, mainly due to lack of hardware to validate on.
> 
> Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
> ---
>  drivers/usb/dwc3/Kconfig           |  10 +
>  drivers/usb/dwc3/Makefile          |   1 +
>  drivers/usb/dwc3/dwc3-meson-g12a.c | 601 +++++++++++++++++++++++++++++
>  3 files changed, 612 insertions(+)
>  create mode 100644 drivers/usb/dwc3/dwc3-meson-g12a.c
> 
> diff --git a/drivers/usb/dwc3/Kconfig b/drivers/usb/dwc3/Kconfig
> index 1a0404fda596..21ce7368d325 100644
> --- a/drivers/usb/dwc3/Kconfig
> +++ b/drivers/usb/dwc3/Kconfig
> @@ -93,6 +93,16 @@ config USB_DWC3_KEYSTONE
>  	  Support of USB2/3 functionality in TI Keystone2 platforms.
>  	  Say 'Y' or 'M' here if you have one such device
>  
> +config USB_DWC3_MESON_G12A
> +       tristate "Amlogic Meson G12A Platforms"
> +       depends on OF && COMMON_CLK
> +       depends on ARCH_MESON || COMPILE_TEST
> +       default USB_DWC3
> +       select USB_ROLE_SWITCH
> +       help
> +         Support USB2/3 functionality in Amlogic G12A platforms.
> +	 Say 'Y' or 'M' if you have one such device.
> +
>  config USB_DWC3_OF_SIMPLE
>         tristate "Generic OF Simple Glue Layer"
>         depends on OF && COMMON_CLK
> diff --git a/drivers/usb/dwc3/Makefile b/drivers/usb/dwc3/Makefile
> index 6e3ef6144e5d..ae86da0dc5bd 100644
> --- a/drivers/usb/dwc3/Makefile
> +++ b/drivers/usb/dwc3/Makefile
> @@ -47,6 +47,7 @@ obj-$(CONFIG_USB_DWC3_EXYNOS)		+= dwc3-exynos.o
>  obj-$(CONFIG_USB_DWC3_PCI)		+= dwc3-pci.o
>  obj-$(CONFIG_USB_DWC3_HAPS)		+= dwc3-haps.o
>  obj-$(CONFIG_USB_DWC3_KEYSTONE)		+= dwc3-keystone.o
> +obj-$(CONFIG_USB_DWC3_MESON_G12A)	+= dwc3-meson-g12a.o
>  obj-$(CONFIG_USB_DWC3_OF_SIMPLE)	+= dwc3-of-simple.o
>  obj-$(CONFIG_USB_DWC3_ST)		+= dwc3-st.o
>  obj-$(CONFIG_USB_DWC3_QCOM)		+= dwc3-qcom.o
> diff --git a/drivers/usb/dwc3/dwc3-meson-g12a.c b/drivers/usb/dwc3/dwc3-meson-g12a.c
> new file mode 100644
> index 000000000000..75942614a034
> --- /dev/null
> +++ b/drivers/usb/dwc3/dwc3-meson-g12a.c
> @@ -0,0 +1,601 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * USB Glue for Amlogic G12A SoCs
> + *
> + * Copyright (c) 2019 BayLibre, SAS
> + * Author: Neil Armstrong <narmstrong@baylibre.com>
> + */
> +
> +/*
> + * The USB is organized with a glue around the DWC3 Controller IP as :
> + * - Control registers for each USB2 Ports
> + * - Control registers for the USB PHY layer
> + * - SuperSpeed PHY can be enabled only if port is used
> + *
> + * TOFIX:
> + * - Add dynamic OTG switching with ID change interrupt
> + */
> +
[...]
> +
> +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;
> +	}
> +
> +	ret = reset_control_reset(priv->reset);
> +	if (ret)
> +		return ret;
> +
> +	ret = dwc3_meson_g12a_get_phys(priv);
> +	if (ret)
> +		return ret;
> +
> +	ret = regulator_enable(priv->vbus);
> +	if (ret)
> +		return ret;
> +
> +	/* Get dr_mode */
> +	priv->otg_mode = usb_get_dr_mode(dev);
> +
> +	dwc3_meson_g12a_usb_init(priv);
> +
> +	/* Set PHY Power */
> +	for (i = 0 ; i < PHY_COUNT ; ++i) {
> +		ret = phy_power_on(priv->phys[i]);
> +		if (ret)
> +			goto err_phys_put;
> +	}
> +
> +	/* Init PHYs */
> +	for (i = 0 ; i < PHY_COUNT ; ++i) {
> +		ret = phy_init(priv->phys[i]);
> +		if (ret)
> +			goto err_phys_power;
> +	}
usually phy_init() first

> +
> +	ret = of_platform_populate(np, NULL, NULL, dev);
> +	if (ret) {
> +		clk_disable_unprepare(priv->clk);
> +		clk_put(priv->clk);
> +
> +		goto err_phys_exit;
> +	}
> +
> +	/* Setup OTG mode corresponding to the ID pin */
> +	if (priv->otg_mode == USB_DR_MODE_OTG) {
> +		/* TOFIX Handle ID mode toggling via IRQ */
> +		otg_id = dwc3_meson_g12a_get_id(priv);
> +		if (otg_id != priv->otg_phy_mode) {
> +			if (dwc3_meson_g12a_otg_mode_set(priv, otg_id))
> +				dev_warn(dev, "Failed to switch OTG mode\n");
> +		}
> +	}
> +
> +	/* Setup role switcher */
> +	priv->switch_desc.usb2_port = dwc3_meson_g12_find_child(dev,
> +								"snps,dwc3");
> +	priv->switch_desc.udc = dwc3_meson_g12_find_child(dev, "snps,dwc2");
> +	priv->switch_desc.allow_userspace_control = true;
> +	priv->switch_desc.set = dwc3_meson_g12a_role_set;
> +	priv->switch_desc.get = dwc3_meson_g12a_role_get;
to me, use a local variable for switch_desc

> +
> +	priv->role_switch = usb_role_switch_register(dev, &priv->switch_desc);
> +	if (IS_ERR(priv->role_switch))
> +		dev_warn(dev, "Unable to register Role Switch\n");
> +
> +	pm_runtime_set_active(dev);
> +	pm_runtime_enable(dev);
> +	pm_runtime_get_sync(dev);
> +
> +	return 0;
> +
> +err_phys_exit:
> +	for (i = 0 ; i < PHY_COUNT ; ++i)
> +		phy_exit(priv->phys[i]);
> +
> +err_phys_power:
> +	for (i = 0 ; i < PHY_COUNT ; ++i)
> +		phy_power_off(priv->phys[i]);
> +
> +err_phys_put:
> +	for (i = 0 ; i < PHY_COUNT ; ++i)
> +		phy_put(priv->phys[i]);
> +
The phys are got by devm_phy_optional_get(), no need call phy_put()
> +	return ret;
> +}
> +
> +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]);
ditto
> +	}
> +
> +	clk_disable_unprepare(priv->clk);
> +	clk_put(priv->clk);
> +
> +	pm_runtime_disable(dev);
> +	pm_runtime_put_noidle(dev);
> +	pm_runtime_set_suspended(dev);
> +
> +	return 0;
> +}
> +
> +static int __maybe_unused dwc3_meson_g12a_runtime_suspend(struct device *dev)
> +{
> +	struct dwc3_meson_g12a	*priv = dev_get_drvdata(dev);
> +
> +	clk_disable(priv->clk);
> +
> +	return 0;
> +}
> +
> +static int __maybe_unused dwc3_meson_g12a_runtime_resume(struct device *dev)
> +{
> +	struct dwc3_meson_g12a	*priv = dev_get_drvdata(dev);
> +
> +	return clk_enable(priv->clk);
> +}
> +
> +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]);
> +
> +	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]);
> +			if (ret)
> +				return ret;
> +		}
> +	}
> +
> +	return 0;
> +}
> +
> +static const struct dev_pm_ops dwc3_meson_g12a_dev_pm_ops = {
> +	SET_SYSTEM_SLEEP_PM_OPS(dwc3_meson_g12a_suspend, dwc3_meson_g12a_resume)
> +	SET_RUNTIME_PM_OPS(dwc3_meson_g12a_runtime_suspend,
> +			dwc3_meson_g12a_runtime_resume, NULL)
> +};
> +
> +static const struct of_device_id dwc3_meson_g12a_match[] = {
> +	{ .compatible = "amlogic,meson-g12a-usb-ctrl" },
> +	{ /* Sentinel */ }
> +};
> +MODULE_DEVICE_TABLE(of, dwc3_meson_g12a_match);
> +
> +static struct platform_driver dwc3_meson_g12a_driver = {
> +	.probe		= dwc3_meson_g12a_probe,
> +	.remove		= dwc3_meson_g12a_remove,
> +	.driver		= {
> +		.name	= "dwc3-meson-g12a",
> +		.of_match_table = dwc3_meson_g12a_match,
> +		.pm	= &dwc3_meson_g12a_dev_pm_ops,
> +	},
> +};
> +
> +module_platform_driver(dwc3_meson_g12a_driver);
> +MODULE_LICENSE("GPL v2");
> +MODULE_DESCRIPTION("Amlogic Meson G12A USB Glue Layer");
> +MODULE_AUTHOR("Neil Armstrong <narmstrong@baylibre.com>");



_______________________________________________
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: Chunfeng Yun <chunfeng.yun@mediatek.com>
To: Neil Armstrong <narmstrong@baylibre.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: Thu, 7 Mar 2019 10:02:56 +0800	[thread overview]
Message-ID: <1551924176.2210.104.camel@mhfsdcap03> (raw)
In-Reply-To: <20190304103846.2060-9-narmstrong@baylibre.com>

Hi,
On Mon, 2019-03-04 at 11:38 +0100, Neil Armstrong wrote:
> Adds support for Amlogic G12A USB Control Glue HW.
> 
> The Amlogic G12A SoC Family embeds 2 USB Controllers :
> - a DWC3 IP configured as Host for USB2 and USB3
> - a DWC2 IP configured as Peripheral USB2 Only
> 
> A glue connects these both controllers to 2 USB2 PHYs, and optionnally
> to an USB3+PCIE Combo PHY shared with the PCIE controller.
> 
> The Glue configures the UTMI 8bit interfaces for the USB2 PHYs, including
> routing of the OTG PHY between the DWC3 and DWC2 controllers, and
> setups the on-chip OTG mode selection for this PHY.
> 
> This drivers supports the on-probe setup of the OTG mode, and manually
> via a debugfs interface. The IRQ mode change detect is yet to be added
> in a future patchset, mainly due to lack of hardware to validate on.
> 
> Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
> ---
>  drivers/usb/dwc3/Kconfig           |  10 +
>  drivers/usb/dwc3/Makefile          |   1 +
>  drivers/usb/dwc3/dwc3-meson-g12a.c | 601 +++++++++++++++++++++++++++++
>  3 files changed, 612 insertions(+)
>  create mode 100644 drivers/usb/dwc3/dwc3-meson-g12a.c
> 
> diff --git a/drivers/usb/dwc3/Kconfig b/drivers/usb/dwc3/Kconfig
> index 1a0404fda596..21ce7368d325 100644
> --- a/drivers/usb/dwc3/Kconfig
> +++ b/drivers/usb/dwc3/Kconfig
> @@ -93,6 +93,16 @@ config USB_DWC3_KEYSTONE
>  	  Support of USB2/3 functionality in TI Keystone2 platforms.
>  	  Say 'Y' or 'M' here if you have one such device
>  
> +config USB_DWC3_MESON_G12A
> +       tristate "Amlogic Meson G12A Platforms"
> +       depends on OF && COMMON_CLK
> +       depends on ARCH_MESON || COMPILE_TEST
> +       default USB_DWC3
> +       select USB_ROLE_SWITCH
> +       help
> +         Support USB2/3 functionality in Amlogic G12A platforms.
> +	 Say 'Y' or 'M' if you have one such device.
> +
>  config USB_DWC3_OF_SIMPLE
>         tristate "Generic OF Simple Glue Layer"
>         depends on OF && COMMON_CLK
> diff --git a/drivers/usb/dwc3/Makefile b/drivers/usb/dwc3/Makefile
> index 6e3ef6144e5d..ae86da0dc5bd 100644
> --- a/drivers/usb/dwc3/Makefile
> +++ b/drivers/usb/dwc3/Makefile
> @@ -47,6 +47,7 @@ obj-$(CONFIG_USB_DWC3_EXYNOS)		+= dwc3-exynos.o
>  obj-$(CONFIG_USB_DWC3_PCI)		+= dwc3-pci.o
>  obj-$(CONFIG_USB_DWC3_HAPS)		+= dwc3-haps.o
>  obj-$(CONFIG_USB_DWC3_KEYSTONE)		+= dwc3-keystone.o
> +obj-$(CONFIG_USB_DWC3_MESON_G12A)	+= dwc3-meson-g12a.o
>  obj-$(CONFIG_USB_DWC3_OF_SIMPLE)	+= dwc3-of-simple.o
>  obj-$(CONFIG_USB_DWC3_ST)		+= dwc3-st.o
>  obj-$(CONFIG_USB_DWC3_QCOM)		+= dwc3-qcom.o
> diff --git a/drivers/usb/dwc3/dwc3-meson-g12a.c b/drivers/usb/dwc3/dwc3-meson-g12a.c
> new file mode 100644
> index 000000000000..75942614a034
> --- /dev/null
> +++ b/drivers/usb/dwc3/dwc3-meson-g12a.c
> @@ -0,0 +1,601 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * USB Glue for Amlogic G12A SoCs
> + *
> + * Copyright (c) 2019 BayLibre, SAS
> + * Author: Neil Armstrong <narmstrong@baylibre.com>
> + */
> +
> +/*
> + * The USB is organized with a glue around the DWC3 Controller IP as :
> + * - Control registers for each USB2 Ports
> + * - Control registers for the USB PHY layer
> + * - SuperSpeed PHY can be enabled only if port is used
> + *
> + * TOFIX:
> + * - Add dynamic OTG switching with ID change interrupt
> + */
> +
[...]
> +
> +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;
> +	}
> +
> +	ret = reset_control_reset(priv->reset);
> +	if (ret)
> +		return ret;
> +
> +	ret = dwc3_meson_g12a_get_phys(priv);
> +	if (ret)
> +		return ret;
> +
> +	ret = regulator_enable(priv->vbus);
> +	if (ret)
> +		return ret;
> +
> +	/* Get dr_mode */
> +	priv->otg_mode = usb_get_dr_mode(dev);
> +
> +	dwc3_meson_g12a_usb_init(priv);
> +
> +	/* Set PHY Power */
> +	for (i = 0 ; i < PHY_COUNT ; ++i) {
> +		ret = phy_power_on(priv->phys[i]);
> +		if (ret)
> +			goto err_phys_put;
> +	}
> +
> +	/* Init PHYs */
> +	for (i = 0 ; i < PHY_COUNT ; ++i) {
> +		ret = phy_init(priv->phys[i]);
> +		if (ret)
> +			goto err_phys_power;
> +	}
usually phy_init() first

> +
> +	ret = of_platform_populate(np, NULL, NULL, dev);
> +	if (ret) {
> +		clk_disable_unprepare(priv->clk);
> +		clk_put(priv->clk);
> +
> +		goto err_phys_exit;
> +	}
> +
> +	/* Setup OTG mode corresponding to the ID pin */
> +	if (priv->otg_mode == USB_DR_MODE_OTG) {
> +		/* TOFIX Handle ID mode toggling via IRQ */
> +		otg_id = dwc3_meson_g12a_get_id(priv);
> +		if (otg_id != priv->otg_phy_mode) {
> +			if (dwc3_meson_g12a_otg_mode_set(priv, otg_id))
> +				dev_warn(dev, "Failed to switch OTG mode\n");
> +		}
> +	}
> +
> +	/* Setup role switcher */
> +	priv->switch_desc.usb2_port = dwc3_meson_g12_find_child(dev,
> +								"snps,dwc3");
> +	priv->switch_desc.udc = dwc3_meson_g12_find_child(dev, "snps,dwc2");
> +	priv->switch_desc.allow_userspace_control = true;
> +	priv->switch_desc.set = dwc3_meson_g12a_role_set;
> +	priv->switch_desc.get = dwc3_meson_g12a_role_get;
to me, use a local variable for switch_desc

> +
> +	priv->role_switch = usb_role_switch_register(dev, &priv->switch_desc);
> +	if (IS_ERR(priv->role_switch))
> +		dev_warn(dev, "Unable to register Role Switch\n");
> +
> +	pm_runtime_set_active(dev);
> +	pm_runtime_enable(dev);
> +	pm_runtime_get_sync(dev);
> +
> +	return 0;
> +
> +err_phys_exit:
> +	for (i = 0 ; i < PHY_COUNT ; ++i)
> +		phy_exit(priv->phys[i]);
> +
> +err_phys_power:
> +	for (i = 0 ; i < PHY_COUNT ; ++i)
> +		phy_power_off(priv->phys[i]);
> +
> +err_phys_put:
> +	for (i = 0 ; i < PHY_COUNT ; ++i)
> +		phy_put(priv->phys[i]);
> +
The phys are got by devm_phy_optional_get(), no need call phy_put()
> +	return ret;
> +}
> +
> +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]);
ditto
> +	}
> +
> +	clk_disable_unprepare(priv->clk);
> +	clk_put(priv->clk);
> +
> +	pm_runtime_disable(dev);
> +	pm_runtime_put_noidle(dev);
> +	pm_runtime_set_suspended(dev);
> +
> +	return 0;
> +}
> +
> +static int __maybe_unused dwc3_meson_g12a_runtime_suspend(struct device *dev)
> +{
> +	struct dwc3_meson_g12a	*priv = dev_get_drvdata(dev);
> +
> +	clk_disable(priv->clk);
> +
> +	return 0;
> +}
> +
> +static int __maybe_unused dwc3_meson_g12a_runtime_resume(struct device *dev)
> +{
> +	struct dwc3_meson_g12a	*priv = dev_get_drvdata(dev);
> +
> +	return clk_enable(priv->clk);
> +}
> +
> +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]);
> +
> +	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]);
> +			if (ret)
> +				return ret;
> +		}
> +	}
> +
> +	return 0;
> +}
> +
> +static const struct dev_pm_ops dwc3_meson_g12a_dev_pm_ops = {
> +	SET_SYSTEM_SLEEP_PM_OPS(dwc3_meson_g12a_suspend, dwc3_meson_g12a_resume)
> +	SET_RUNTIME_PM_OPS(dwc3_meson_g12a_runtime_suspend,
> +			dwc3_meson_g12a_runtime_resume, NULL)
> +};
> +
> +static const struct of_device_id dwc3_meson_g12a_match[] = {
> +	{ .compatible = "amlogic,meson-g12a-usb-ctrl" },
> +	{ /* Sentinel */ }
> +};
> +MODULE_DEVICE_TABLE(of, dwc3_meson_g12a_match);
> +
> +static struct platform_driver dwc3_meson_g12a_driver = {
> +	.probe		= dwc3_meson_g12a_probe,
> +	.remove		= dwc3_meson_g12a_remove,
> +	.driver		= {
> +		.name	= "dwc3-meson-g12a",
> +		.of_match_table = dwc3_meson_g12a_match,
> +		.pm	= &dwc3_meson_g12a_dev_pm_ops,
> +	},
> +};
> +
> +module_platform_driver(dwc3_meson_g12a_driver);
> +MODULE_LICENSE("GPL v2");
> +MODULE_DESCRIPTION("Amlogic Meson G12A USB Glue Layer");
> +MODULE_AUTHOR("Neil Armstrong <narmstrong@baylibre.com>");



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

  reply	other threads:[~2019-03-07  2:03 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   ` Chunfeng Yun [this message]
2019-03-07  2:02     ` [PATCH v2 8/8] " 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     ` [PATCH v2 8/8] " Neil Armstrong
2019-03-13 13:07       ` 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=1551924176.2210.104.camel@mhfsdcap03 \
    --to=chunfeng.yun@mediatek.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=narmstrong@baylibre.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.