* [PATCH v4 00/20] NVIDIA Tegra USB2 drivers clean up
@ 2020-01-06 1:33 Dmitry Osipenko
2020-01-06 1:33 ` [PATCH v4 01/20] dt-binding: usb: ci-hdrc-usb2: Document NVIDIA Tegra support Dmitry Osipenko
` (19 more replies)
0 siblings, 20 replies; 23+ messages in thread
From: Dmitry Osipenko @ 2020-01-06 1:33 UTC (permalink / raw)
To: Greg Kroah-Hartman, Peter Chen, Thierry Reding, Jonathan Hunter,
Felipe Balbi, Michał Mirosław
Cc: linux-usb, linux-tegra, linux-kernel
Hello,
This patch series brings the NVIDIA Tegra USB2 PHY driver into a better
shape by refactoring code to match upstream standards, the ChipIdea/Tegra UDC
driver also gets a minor update. Please review and apply, thanks in advance!
Changelog:
v4: - Dropped the request_module() from "Add USB_TEGRA_PHY to driver's
dependencies" because it resulted in a bit too many questions during
review and since it won't be needed once Tegra EHCI driver will be
squashed into the CI anyways.
- Factored out clean up of ulpi_phy_power_off into a separate patch and
improved it a bit move by disabling clock *after* asserting reset:
usb: phy: tegra: Clean up ulpi_phy_power_off
- Cleaned up ULPI reset-GPIO changes that were messed up a tad in v3,
thanks to Michał Mirosław for reviewing it in v3.
- Dropped the "Assert reset on ULPI close instead of deasserting it"
patch because turned out that the problem was introduced by an earlier
patch in this series, which is fixed now.
- Added missed tegra_usb_phy_power_off to tegra_usb_phy_shutdown() in
the "Hook up init/shutdown callbacks" patch.
- I found out that PHY-enable refcount is broken after drivers reloading,
added these new patches in a result:
usb: phy: tegra: Keep track of power on-off state
usb: host: ehci-tegra: Stop managing PHY's power
- Added patch to clean up included headers in the PHY driver:
usb: phy: tegra: Clean up included headers
v3: - The "Perform general clean up of the code" patch now cleans up couple
more minor crumbs.
- Added more "clean up" patches:
usb: phy: tegra: Disable VBUS regulator on tegra_usb_phy_init failure
usb: phy: tegra: Move utmip_pad_count checking under lock
usb: phy: tegra: Keep CPU interrupts enabled
usb: host: ehci-tegra: Remove unused fields from tegra_ehci_hcd
- I noticed that ULPI's reset is getting erroneously deasserted on
PHY's shutdown, this is fixed in these new patches:
usb: phy: tegra: Assert reset on ULPI close instead of deasserting it
usb: phy: tegra: Use device-tree notion of reset-GPIO's active-state
v2: - The "usb: phy: tegra: Hook up init/shutdown callbacks" patch was
updated and now it does a better job in regards to checking whether
PHY is initialized before it is started to be used and whether there
is a double init/shutdown. This allows to factor out the ChipIdea's
driver change into a separate patch, which was requested by Peter Chen
in a review comment to v1. In a result there is this new patch:
usb: chipidea: tegra: Stop managing PHY's power
- Added few more new patches:
usb: phy: tegra: Use generic stub for a missing VBUS regulator
I noticed that VBUS regulator usage could be cleaned up a tad as well.
usb: ulpi: Add resource-managed variant of otg_ulpi_create()
usb: phy: tegra: Use devm_otg_ulpi_create()
usb: phy: tegra: Use u32 for hardware register variables
These patches are made in response to review comments that were made
by Thierry Reding to v1.
I also noticed that phy_tegra_usb isn't getting auto-loaded while it
should be. This is fixed in this new patch:
usb: chipidea: tegra: Add USB_TEGRA_PHY to driver's dependencies
Dmitry Osipenko (20):
dt-binding: usb: ci-hdrc-usb2: Document NVIDIA Tegra support
usb: host: ehci-tegra: Correct teardown order of driver's removal
usb: phy: tegra: Clean up ulpi_phy_power_off
usb: phy: tegra: Keep track of power on-off state
usb: phy: tegra: Hook up init/shutdown callbacks
usb: phy: tegra: Perform general clean up of the code
usb: phy: tegra: Clean up included headers
usb: phy: tegra: Use relaxed versions of readl/writel
usb: phy: tegra: Use generic stub for a missing VBUS regulator
usb: ulpi: Add resource-managed variant of otg_ulpi_create()
usb: phy: tegra: Use devm_otg_ulpi_create()
usb: phy: tegra: Use u32 for hardware register variables
usb: phy: tegra: Use device-tree notion of reset-GPIO's active-state
usb: phy: tegra: Disable VBUS regulator on tegra_usb_phy_init failure
usb: phy: tegra: Move utmip_pad_count checking under lock
usb: phy: tegra: Keep CPU interrupts enabled
usb: chipidea: tegra: Stop managing PHY's power
usb: chipidea: tegra: Add USB_TEGRA_PHY to driver's dependencies
usb: host: ehci-tegra: Stop managing PHY's power
usb: host: ehci-tegra: Remove unused fields from tegra_ehci_hcd
.../devicetree/bindings/usb/ci-hdrc-usb2.txt | 4 +
drivers/usb/chipidea/Kconfig | 1 +
drivers/usb/chipidea/ci_hdrc_tegra.c | 9 -
drivers/usb/host/ehci-tegra.c | 16 +-
drivers/usb/phy/phy-tegra-usb.c | 896 +++++++++---------
drivers/usb/phy/phy-ulpi.c | 48 +-
include/linux/usb/tegra_usb_phy.h | 4 +-
include/linux/usb/ulpi.h | 11 +
8 files changed, 530 insertions(+), 459 deletions(-)
--
2.24.0
^ permalink raw reply [flat|nested] 23+ messages in thread
* [PATCH v4 01/20] dt-binding: usb: ci-hdrc-usb2: Document NVIDIA Tegra support
2020-01-06 1:33 [PATCH v4 00/20] NVIDIA Tegra USB2 drivers clean up Dmitry Osipenko
@ 2020-01-06 1:33 ` Dmitry Osipenko
2020-01-06 1:33 ` [PATCH v4 02/20] usb: host: ehci-tegra: Correct teardown order of driver's removal Dmitry Osipenko
` (18 subsequent siblings)
19 siblings, 0 replies; 23+ messages in thread
From: Dmitry Osipenko @ 2020-01-06 1:33 UTC (permalink / raw)
To: Greg Kroah-Hartman, Peter Chen, Thierry Reding, Jonathan Hunter,
Felipe Balbi, Michał Mirosław
Cc: linux-usb, linux-tegra, linux-kernel
NVIDIA Tegra SoCs use ChipIdea silicon IP for the USB controllers.
Acked-by: Peter Chen <peter.chen@nxp.com>
Acked-by: Thierry Reding <treding@nvidia.com>
Acked-by: Rob Herring <robh@kernel.org>
Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
---
Documentation/devicetree/bindings/usb/ci-hdrc-usb2.txt | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/Documentation/devicetree/bindings/usb/ci-hdrc-usb2.txt b/Documentation/devicetree/bindings/usb/ci-hdrc-usb2.txt
index cfc9f40ab641..51376cbe5f3d 100644
--- a/Documentation/devicetree/bindings/usb/ci-hdrc-usb2.txt
+++ b/Documentation/devicetree/bindings/usb/ci-hdrc-usb2.txt
@@ -15,6 +15,10 @@ Required properties:
"qcom,ci-hdrc"
"chipidea,usb2"
"xlnx,zynq-usb-2.20a"
+ "nvidia,tegra20-udc"
+ "nvidia,tegra30-udc"
+ "nvidia,tegra114-udc"
+ "nvidia,tegra124-udc"
- reg: base address and length of the registers
- interrupts: interrupt for the USB controller
--
2.24.0
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCH v4 02/20] usb: host: ehci-tegra: Correct teardown order of driver's removal
2020-01-06 1:33 [PATCH v4 00/20] NVIDIA Tegra USB2 drivers clean up Dmitry Osipenko
2020-01-06 1:33 ` [PATCH v4 01/20] dt-binding: usb: ci-hdrc-usb2: Document NVIDIA Tegra support Dmitry Osipenko
@ 2020-01-06 1:33 ` Dmitry Osipenko
2020-01-06 1:33 ` [PATCH v4 03/20] usb: phy: tegra: Clean up ulpi_phy_power_off Dmitry Osipenko
` (17 subsequent siblings)
19 siblings, 0 replies; 23+ messages in thread
From: Dmitry Osipenko @ 2020-01-06 1:33 UTC (permalink / raw)
To: Greg Kroah-Hartman, Peter Chen, Thierry Reding, Jonathan Hunter,
Felipe Balbi, Michał Mirosław
Cc: linux-usb, linux-tegra, linux-kernel
I found that PHY's enable refcounting was broken and after fixing it
I also found that machine started to hang after EHCI driver module
removal. Turned out that the teardown order is incorrect because HCD must
be unregistered *before* PHY's disabling. Note that it is also not correct
to assert the shared reset during of driver's removal because PHY takes
care of resetting shared pads and thus it's better to remove that part
from the EHCI driver.
Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
---
drivers/usb/host/ehci-tegra.c | 8 +-------
1 file changed, 1 insertion(+), 7 deletions(-)
diff --git a/drivers/usb/host/ehci-tegra.c b/drivers/usb/host/ehci-tegra.c
index 4d2cdec4cb78..32483bef046b 100644
--- a/drivers/usb/host/ehci-tegra.c
+++ b/drivers/usb/host/ehci-tegra.c
@@ -521,16 +521,10 @@ static int tegra_ehci_remove(struct platform_device *pdev)
struct tegra_ehci_hcd *tegra =
(struct tegra_ehci_hcd *)hcd_to_ehci(hcd)->priv;
+ usb_remove_hcd(hcd);
otg_set_host(hcd->usb_phy->otg, NULL);
-
usb_phy_shutdown(hcd->usb_phy);
- usb_remove_hcd(hcd);
-
- reset_control_assert(tegra->rst);
- udelay(1);
-
clk_disable_unprepare(tegra->clk);
-
usb_put_hcd(hcd);
return 0;
--
2.24.0
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCH v4 03/20] usb: phy: tegra: Clean up ulpi_phy_power_off
2020-01-06 1:33 [PATCH v4 00/20] NVIDIA Tegra USB2 drivers clean up Dmitry Osipenko
2020-01-06 1:33 ` [PATCH v4 01/20] dt-binding: usb: ci-hdrc-usb2: Document NVIDIA Tegra support Dmitry Osipenko
2020-01-06 1:33 ` [PATCH v4 02/20] usb: host: ehci-tegra: Correct teardown order of driver's removal Dmitry Osipenko
@ 2020-01-06 1:33 ` Dmitry Osipenko
2020-01-06 1:34 ` [PATCH v4 04/20] usb: phy: tegra: Keep track of power on-off state Dmitry Osipenko
` (16 subsequent siblings)
19 siblings, 0 replies; 23+ messages in thread
From: Dmitry Osipenko @ 2020-01-06 1:33 UTC (permalink / raw)
To: Greg Kroah-Hartman, Peter Chen, Thierry Reding, Jonathan Hunter,
Felipe Balbi, Michał Mirosław
Cc: linux-usb, linux-tegra, linux-kernel
Firstly, the PHY's clock needs to unprepared to keep prepare count
balanced. Secondly, downstream code suggests that reset is synchronous
and thus it should be asserted before disabling clock.
Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
---
drivers/usb/phy/phy-tegra-usb.c | 15 +++++++++++++--
1 file changed, 13 insertions(+), 2 deletions(-)
diff --git a/drivers/usb/phy/phy-tegra-usb.c b/drivers/usb/phy/phy-tegra-usb.c
index ea7ef1dc0b42..99acfde4ab8d 100644
--- a/drivers/usb/phy/phy-tegra-usb.c
+++ b/drivers/usb/phy/phy-tegra-usb.c
@@ -757,8 +757,19 @@ static int ulpi_phy_power_on(struct tegra_usb_phy *phy)
static int ulpi_phy_power_off(struct tegra_usb_phy *phy)
{
- clk_disable(phy->clk);
- return gpio_direction_output(phy->reset_gpio, 0);
+ int err;
+
+ err = gpio_direction_output(phy->reset_gpio, 0);
+ if (err) {
+ dev_err(phy->u_phy.dev, "reset GPIO not asserted: %d\n", err);
+ return err;
+ }
+
+ usleep_range(5000, 6000);
+
+ clk_disable_unprepare(phy->clk);
+
+ return 0;
}
static void tegra_usb_phy_close(struct tegra_usb_phy *phy)
--
2.24.0
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCH v4 04/20] usb: phy: tegra: Keep track of power on-off state
2020-01-06 1:33 [PATCH v4 00/20] NVIDIA Tegra USB2 drivers clean up Dmitry Osipenko
` (2 preceding siblings ...)
2020-01-06 1:33 ` [PATCH v4 03/20] usb: phy: tegra: Clean up ulpi_phy_power_off Dmitry Osipenko
@ 2020-01-06 1:34 ` Dmitry Osipenko
2020-01-06 1:34 ` [PATCH v4 05/20] usb: phy: tegra: Hook up init/shutdown callbacks Dmitry Osipenko
` (15 subsequent siblings)
19 siblings, 0 replies; 23+ messages in thread
From: Dmitry Osipenko @ 2020-01-06 1:34 UTC (permalink / raw)
To: Greg Kroah-Hartman, Peter Chen, Thierry Reding, Jonathan Hunter,
Felipe Balbi, Michał Mirosław
Cc: linux-usb, linux-tegra, linux-kernel
The PHY driver should keep track of the enable state, otherwise enable
refcount is screwed if USB driver tries to enable PHY when it is already
enabled. This will be the case for ChipIdea and Tegra EHCI drivers once
PHY driver will gain support for the init/shutdown callbacks.
Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
---
drivers/usb/phy/phy-tegra-usb.c | 30 ++++++++++++++++++++++++++----
include/linux/usb/tegra_usb_phy.h | 1 +
2 files changed, 27 insertions(+), 4 deletions(-)
diff --git a/drivers/usb/phy/phy-tegra-usb.c b/drivers/usb/phy/phy-tegra-usb.c
index 99acfde4ab8d..88466c7f13e6 100644
--- a/drivers/usb/phy/phy-tegra-usb.c
+++ b/drivers/usb/phy/phy-tegra-usb.c
@@ -785,18 +785,40 @@ static void tegra_usb_phy_close(struct tegra_usb_phy *phy)
static int tegra_usb_phy_power_on(struct tegra_usb_phy *phy)
{
+ int err;
+
+ if (phy->powered_on)
+ return 0;
+
if (phy->is_ulpi_phy)
- return ulpi_phy_power_on(phy);
+ err = ulpi_phy_power_on(phy);
else
- return utmi_phy_power_on(phy);
+ err = utmi_phy_power_on(phy);
+ if (err)
+ return err;
+
+ phy->powered_on = true;
+
+ return 0;
}
static int tegra_usb_phy_power_off(struct tegra_usb_phy *phy)
{
+ int err;
+
+ if (!phy->powered_on)
+ return 0;
+
if (phy->is_ulpi_phy)
- return ulpi_phy_power_off(phy);
+ err = ulpi_phy_power_off(phy);
else
- return utmi_phy_power_off(phy);
+ err = utmi_phy_power_off(phy);
+ if (err)
+ return err;
+
+ phy->powered_on = false;
+
+ return 0;
}
static int tegra_usb_phy_suspend(struct usb_phy *x, int suspend)
diff --git a/include/linux/usb/tegra_usb_phy.h b/include/linux/usb/tegra_usb_phy.h
index 0c5c3ea8b2d7..3ae73bdc6245 100644
--- a/include/linux/usb/tegra_usb_phy.h
+++ b/include/linux/usb/tegra_usb_phy.h
@@ -78,6 +78,7 @@ struct tegra_usb_phy {
bool is_ulpi_phy;
int reset_gpio;
struct reset_control *pad_rst;
+ bool powered_on;
};
void tegra_usb_phy_preresume(struct usb_phy *phy);
--
2.24.0
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCH v4 05/20] usb: phy: tegra: Hook up init/shutdown callbacks
2020-01-06 1:33 [PATCH v4 00/20] NVIDIA Tegra USB2 drivers clean up Dmitry Osipenko
` (3 preceding siblings ...)
2020-01-06 1:34 ` [PATCH v4 04/20] usb: phy: tegra: Keep track of power on-off state Dmitry Osipenko
@ 2020-01-06 1:34 ` Dmitry Osipenko
2020-01-06 1:34 ` [PATCH v4 06/20] usb: phy: tegra: Perform general clean up of the code Dmitry Osipenko
` (14 subsequent siblings)
19 siblings, 0 replies; 23+ messages in thread
From: Dmitry Osipenko @ 2020-01-06 1:34 UTC (permalink / raw)
To: Greg Kroah-Hartman, Peter Chen, Thierry Reding, Jonathan Hunter,
Felipe Balbi, Michał Mirosław
Cc: linux-usb, linux-tegra, linux-kernel
Generic PHY provides init/shutdown callbacks which allow USB-host drivers
to abstract PHY's hardware management in a common way. This change allows
to remove Tegra-specific PHY handling from the ChipIdea driver.
Note that ChipIdea's driver shall be changed at the same time because it
turns PHY ON without the PHY's initialization and this doesn't work now,
resulting in a NULL dereference of phy->freq because it's set during of
the PHY's initialization.
Acked-by: Peter Chen <peter.chen@nxp.com>
Acked-by: Thierry Reding <treding@nvidia.com>
Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
---
drivers/usb/phy/phy-tegra-usb.c | 180 +++++++++++++++++++-------------
1 file changed, 110 insertions(+), 70 deletions(-)
diff --git a/drivers/usb/phy/phy-tegra-usb.c b/drivers/usb/phy/phy-tegra-usb.c
index 88466c7f13e6..664259d74658 100644
--- a/drivers/usb/phy/phy-tegra-usb.c
+++ b/drivers/usb/phy/phy-tegra-usb.c
@@ -238,23 +238,6 @@ static int utmip_pad_open(struct tegra_usb_phy *phy)
{
int ret;
- phy->pad_clk = devm_clk_get(phy->u_phy.dev, "utmi-pads");
- if (IS_ERR(phy->pad_clk)) {
- ret = PTR_ERR(phy->pad_clk);
- dev_err(phy->u_phy.dev,
- "Failed to get UTMIP pad clock: %d\n", ret);
- return ret;
- }
-
- phy->pad_rst = devm_reset_control_get_optional_shared(
- phy->u_phy.dev, "utmi-pads");
- if (IS_ERR(phy->pad_rst)) {
- ret = PTR_ERR(phy->pad_rst);
- dev_err(phy->u_phy.dev,
- "Failed to get UTMI-pads reset: %d\n", ret);
- return ret;
- }
-
ret = clk_prepare_enable(phy->pad_clk);
if (ret) {
dev_err(phy->u_phy.dev,
@@ -772,17 +755,6 @@ static int ulpi_phy_power_off(struct tegra_usb_phy *phy)
return 0;
}
-static void tegra_usb_phy_close(struct tegra_usb_phy *phy)
-{
- if (!IS_ERR(phy->vbus))
- regulator_disable(phy->vbus);
-
- if (!phy->is_ulpi_phy)
- utmip_pad_close(phy);
-
- clk_disable_unprepare(phy->pll_u);
-}
-
static int tegra_usb_phy_power_on(struct tegra_usb_phy *phy)
{
int err;
@@ -821,9 +793,34 @@ static int tegra_usb_phy_power_off(struct tegra_usb_phy *phy)
return 0;
}
-static int tegra_usb_phy_suspend(struct usb_phy *x, int suspend)
+static void tegra_usb_phy_shutdown(struct usb_phy *u_phy)
+{
+ struct tegra_usb_phy *phy = container_of(u_phy, struct tegra_usb_phy,
+ u_phy);
+
+ if (WARN_ON(!phy->freq))
+ return;
+
+ tegra_usb_phy_power_off(phy);
+
+ if (!phy->is_ulpi_phy)
+ utmip_pad_close(phy);
+
+ if (!IS_ERR(phy->vbus))
+ regulator_disable(phy->vbus);
+
+ clk_disable_unprepare(phy->pll_u);
+
+ phy->freq = NULL;
+}
+
+static int tegra_usb_phy_set_suspend(struct usb_phy *x, int suspend)
{
struct tegra_usb_phy *phy = container_of(x, struct tegra_usb_phy, u_phy);
+
+ if (WARN_ON(!phy->freq))
+ return -EINVAL;
+
if (suspend)
return tegra_usb_phy_power_off(phy);
else
@@ -834,53 +831,27 @@ static int ulpi_open(struct tegra_usb_phy *phy)
{
int err;
- phy->clk = devm_clk_get(phy->u_phy.dev, "ulpi-link");
- if (IS_ERR(phy->clk)) {
- err = PTR_ERR(phy->clk);
- dev_err(phy->u_phy.dev, "Failed to get ULPI clock: %d\n", err);
- return err;
- }
-
- err = devm_gpio_request(phy->u_phy.dev, phy->reset_gpio,
- "ulpi_phy_reset_b");
- if (err < 0) {
- dev_err(phy->u_phy.dev, "Request failed for GPIO %d: %d\n",
- phy->reset_gpio, err);
- return err;
- }
-
err = gpio_direction_output(phy->reset_gpio, 0);
if (err < 0) {
dev_err(phy->u_phy.dev,
- "GPIO %d direction not set to output: %d\n",
+ "ULPI reset GPIO %d direction not asserted: %d\n",
phy->reset_gpio, err);
return err;
}
- phy->ulpi = otg_ulpi_create(&ulpi_viewport_access_ops, 0);
- if (!phy->ulpi) {
- dev_err(phy->u_phy.dev, "Failed to create ULPI OTG\n");
- err = -ENOMEM;
- return err;
- }
-
- phy->ulpi->io_priv = phy->regs + ULPI_VIEWPORT;
return 0;
}
-static int tegra_usb_phy_init(struct tegra_usb_phy *phy)
+static int tegra_usb_phy_init(struct usb_phy *u_phy)
{
+ struct tegra_usb_phy *phy = container_of(u_phy, struct tegra_usb_phy,
+ u_phy);
unsigned long parent_rate;
int i;
int err;
- phy->pll_u = devm_clk_get(phy->u_phy.dev, "pll_u");
- if (IS_ERR(phy->pll_u)) {
- err = PTR_ERR(phy->pll_u);
- dev_err(phy->u_phy.dev,
- "Failed to get pll_u clock: %d\n", err);
- return err;
- }
+ if (WARN_ON(phy->freq))
+ return 0;
err = clk_prepare_enable(phy->pll_u);
if (err)
@@ -917,10 +888,20 @@ static int tegra_usb_phy_init(struct tegra_usb_phy *phy)
if (err < 0)
goto fail;
+ err = tegra_usb_phy_power_on(phy);
+ if (err)
+ goto close_phy;
+
return 0;
+close_phy:
+ if (!phy->is_ulpi_phy)
+ utmip_pad_close(phy);
fail:
clk_disable_unprepare(phy->pll_u);
+
+ phy->freq = NULL;
+
return err;
}
@@ -1167,22 +1148,77 @@ static int tegra_usb_phy_probe(struct platform_device *pdev)
tegra_phy->vbus = ERR_PTR(-ENODEV);
}
- tegra_phy->u_phy.dev = &pdev->dev;
- err = tegra_usb_phy_init(tegra_phy);
- if (err < 0)
+ tegra_phy->pll_u = devm_clk_get(&pdev->dev, "pll_u");
+ err = PTR_ERR_OR_ZERO(tegra_phy->pll_u);
+ if (err) {
+ dev_err(&pdev->dev, "Failed to get pll_u clock: %d\n", err);
return err;
+ }
+
+ if (tegra_phy->is_ulpi_phy) {
+ tegra_phy->clk = devm_clk_get(&pdev->dev, "ulpi-link");
+ err = PTR_ERR_OR_ZERO(tegra_phy->clk);
+ if (err) {
+ dev_err(&pdev->dev,
+ "Failed to get ULPI clock: %d\n", err);
+ return err;
+ }
- tegra_phy->u_phy.set_suspend = tegra_usb_phy_suspend;
+ err = devm_gpio_request(&pdev->dev, tegra_phy->reset_gpio,
+ "ulpi_phy_reset_b");
+ if (err < 0) {
+ dev_err(&pdev->dev, "Request failed for GPIO %d: %d\n",
+ tegra_phy->reset_gpio, err);
+ return err;
+ }
+
+ tegra_phy->ulpi = otg_ulpi_create(&ulpi_viewport_access_ops, 0);
+ if (!tegra_phy->ulpi) {
+ dev_err(&pdev->dev, "Failed to create ULPI OTG\n");
+ err = -ENOMEM;
+ return err;
+ }
+
+ tegra_phy->ulpi->io_priv = tegra_phy->regs + ULPI_VIEWPORT;
+ } else {
+ tegra_phy->pad_clk = devm_clk_get(&pdev->dev, "utmi-pads");
+ err = PTR_ERR_OR_ZERO(tegra_phy->pad_clk);
+ if (err) {
+ dev_err(&pdev->dev,
+ "Failed to get UTMIP pad clock: %d\n", err);
+ return err;
+ }
+
+ tegra_phy->pad_rst = devm_reset_control_get_optional_shared(
+ &pdev->dev, "utmi-pads");
+ err = PTR_ERR_OR_ZERO(tegra_phy->pad_rst);
+ if (err) {
+ dev_err(&pdev->dev,
+ "Failed to get UTMI-pads reset: %d\n", err);
+ return err;
+ }
+ }
+
+ tegra_phy->u_phy.dev = &pdev->dev;
+ tegra_phy->u_phy.init = tegra_usb_phy_init;
+ tegra_phy->u_phy.shutdown = tegra_usb_phy_shutdown;
+ tegra_phy->u_phy.set_suspend = tegra_usb_phy_set_suspend;
platform_set_drvdata(pdev, tegra_phy);
err = usb_add_phy_dev(&tegra_phy->u_phy);
- if (err < 0) {
- tegra_usb_phy_close(tegra_phy);
- return err;
- }
+ if (err < 0)
+ goto free_ulpi;
return 0;
+
+free_ulpi:
+ if (tegra_phy->ulpi) {
+ kfree(tegra_phy->ulpi->otg);
+ kfree(tegra_phy->ulpi);
+ }
+
+ return err;
}
static int tegra_usb_phy_remove(struct platform_device *pdev)
@@ -1190,7 +1226,11 @@ static int tegra_usb_phy_remove(struct platform_device *pdev)
struct tegra_usb_phy *tegra_phy = platform_get_drvdata(pdev);
usb_remove_phy(&tegra_phy->u_phy);
- tegra_usb_phy_close(tegra_phy);
+
+ if (tegra_phy->ulpi) {
+ kfree(tegra_phy->ulpi->otg);
+ kfree(tegra_phy->ulpi);
+ }
return 0;
}
--
2.24.0
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCH v4 06/20] usb: phy: tegra: Perform general clean up of the code
2020-01-06 1:33 [PATCH v4 00/20] NVIDIA Tegra USB2 drivers clean up Dmitry Osipenko
` (4 preceding siblings ...)
2020-01-06 1:34 ` [PATCH v4 05/20] usb: phy: tegra: Hook up init/shutdown callbacks Dmitry Osipenko
@ 2020-01-06 1:34 ` Dmitry Osipenko
2020-01-06 1:34 ` [PATCH v4 07/20] usb: phy: tegra: Clean up included headers Dmitry Osipenko
` (13 subsequent siblings)
19 siblings, 0 replies; 23+ messages in thread
From: Dmitry Osipenko @ 2020-01-06 1:34 UTC (permalink / raw)
To: Greg Kroah-Hartman, Peter Chen, Thierry Reding, Jonathan Hunter,
Felipe Balbi, Michał Mirosław
Cc: linux-usb, linux-tegra, linux-kernel
This patch fixes few dozens of legit checkpatch warnings, adds missed
handling of potential error-cases and prettifies code where makes sense.
All these clean-up changes are quite minor and do not fix any real
problems.
Acked-by: Thierry Reding <treding@nvidia.com>
Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
---
drivers/usb/phy/phy-tegra-usb.c | 485 +++++++++++++++++---------------
1 file changed, 254 insertions(+), 231 deletions(-)
diff --git a/drivers/usb/phy/phy-tegra-usb.c b/drivers/usb/phy/phy-tegra-usb.c
index 664259d74658..c045f44ea964 100644
--- a/drivers/usb/phy/phy-tegra-usb.c
+++ b/drivers/usb/phy/phy-tegra-usb.c
@@ -28,35 +28,35 @@
#include <linux/usb/tegra_usb_phy.h>
#include <linux/regulator/consumer.h>
-#define ULPI_VIEWPORT 0x170
+#define ULPI_VIEWPORT 0x170
/* PORTSC PTS/PHCD bits, Tegra20 only */
-#define TEGRA_USB_PORTSC1 0x184
-#define TEGRA_USB_PORTSC1_PTS(x) (((x) & 0x3) << 30)
-#define TEGRA_USB_PORTSC1_PHCD (1 << 23)
+#define TEGRA_USB_PORTSC1 0x184
+#define TEGRA_USB_PORTSC1_PTS(x) (((x) & 0x3) << 30)
+#define TEGRA_USB_PORTSC1_PHCD BIT(23)
/* HOSTPC1 PTS/PHCD bits, Tegra30 and above */
-#define TEGRA_USB_HOSTPC1_DEVLC 0x1b4
-#define TEGRA_USB_HOSTPC1_DEVLC_PTS(x) (((x) & 0x7) << 29)
-#define TEGRA_USB_HOSTPC1_DEVLC_PHCD (1 << 22)
+#define TEGRA_USB_HOSTPC1_DEVLC 0x1b4
+#define TEGRA_USB_HOSTPC1_DEVLC_PTS(x) (((x) & 0x7) << 29)
+#define TEGRA_USB_HOSTPC1_DEVLC_PHCD BIT(22)
/* Bits of PORTSC1, which will get cleared by writing 1 into them */
#define TEGRA_PORTSC1_RWC_BITS (PORT_CSC | PORT_PEC | PORT_OCC)
-#define USB_SUSP_CTRL 0x400
-#define USB_WAKE_ON_CNNT_EN_DEV (1 << 3)
-#define USB_WAKE_ON_DISCON_EN_DEV (1 << 4)
-#define USB_SUSP_CLR (1 << 5)
-#define USB_PHY_CLK_VALID (1 << 7)
-#define UTMIP_RESET (1 << 11)
-#define UHSIC_RESET (1 << 11)
-#define UTMIP_PHY_ENABLE (1 << 12)
-#define ULPI_PHY_ENABLE (1 << 13)
-#define USB_SUSP_SET (1 << 14)
-#define USB_WAKEUP_DEBOUNCE_COUNT(x) (((x) & 0x7) << 16)
-
-#define USB1_LEGACY_CTRL 0x410
-#define USB1_NO_LEGACY_MODE (1 << 0)
+#define USB_SUSP_CTRL 0x400
+#define USB_WAKE_ON_CNNT_EN_DEV BIT(3)
+#define USB_WAKE_ON_DISCON_EN_DEV BIT(4)
+#define USB_SUSP_CLR BIT(5)
+#define USB_PHY_CLK_VALID BIT(7)
+#define UTMIP_RESET BIT(11)
+#define UHSIC_RESET BIT(11)
+#define UTMIP_PHY_ENABLE BIT(12)
+#define ULPI_PHY_ENABLE BIT(13)
+#define USB_SUSP_SET BIT(14)
+#define USB_WAKEUP_DEBOUNCE_COUNT(x) (((x) & 0x7) << 16)
+
+#define USB1_LEGACY_CTRL 0x410
+#define USB1_NO_LEGACY_MODE BIT(0)
#define USB1_VBUS_SENSE_CTL_MASK (3 << 1)
#define USB1_VBUS_SENSE_CTL_VBUS_WAKEUP (0 << 1)
#define USB1_VBUS_SENSE_CTL_AB_SESS_VLD_OR_VBUS_WAKEUP \
@@ -64,94 +64,94 @@
#define USB1_VBUS_SENSE_CTL_AB_SESS_VLD (2 << 1)
#define USB1_VBUS_SENSE_CTL_A_SESS_VLD (3 << 1)
-#define ULPI_TIMING_CTRL_0 0x424
-#define ULPI_OUTPUT_PINMUX_BYP (1 << 10)
-#define ULPI_CLKOUT_PINMUX_BYP (1 << 11)
+#define ULPI_TIMING_CTRL_0 0x424
+#define ULPI_OUTPUT_PINMUX_BYP BIT(10)
+#define ULPI_CLKOUT_PINMUX_BYP BIT(11)
-#define ULPI_TIMING_CTRL_1 0x428
-#define ULPI_DATA_TRIMMER_LOAD (1 << 0)
-#define ULPI_DATA_TRIMMER_SEL(x) (((x) & 0x7) << 1)
-#define ULPI_STPDIRNXT_TRIMMER_LOAD (1 << 16)
-#define ULPI_STPDIRNXT_TRIMMER_SEL(x) (((x) & 0x7) << 17)
-#define ULPI_DIR_TRIMMER_LOAD (1 << 24)
-#define ULPI_DIR_TRIMMER_SEL(x) (((x) & 0x7) << 25)
+#define ULPI_TIMING_CTRL_1 0x428
+#define ULPI_DATA_TRIMMER_LOAD BIT(0)
+#define ULPI_DATA_TRIMMER_SEL(x) (((x) & 0x7) << 1)
+#define ULPI_STPDIRNXT_TRIMMER_LOAD BIT(16)
+#define ULPI_STPDIRNXT_TRIMMER_SEL(x) (((x) & 0x7) << 17)
+#define ULPI_DIR_TRIMMER_LOAD BIT(24)
+#define ULPI_DIR_TRIMMER_SEL(x) (((x) & 0x7) << 25)
-#define UTMIP_PLL_CFG1 0x804
+#define UTMIP_PLL_CFG1 0x804
#define UTMIP_XTAL_FREQ_COUNT(x) (((x) & 0xfff) << 0)
#define UTMIP_PLLU_ENABLE_DLY_COUNT(x) (((x) & 0x1f) << 27)
-#define UTMIP_XCVR_CFG0 0x808
+#define UTMIP_XCVR_CFG0 0x808
#define UTMIP_XCVR_SETUP(x) (((x) & 0xf) << 0)
#define UTMIP_XCVR_SETUP_MSB(x) ((((x) & 0x70) >> 4) << 22)
#define UTMIP_XCVR_LSRSLEW(x) (((x) & 0x3) << 8)
#define UTMIP_XCVR_LSFSLEW(x) (((x) & 0x3) << 10)
-#define UTMIP_FORCE_PD_POWERDOWN (1 << 14)
-#define UTMIP_FORCE_PD2_POWERDOWN (1 << 16)
-#define UTMIP_FORCE_PDZI_POWERDOWN (1 << 18)
-#define UTMIP_XCVR_LSBIAS_SEL (1 << 21)
+#define UTMIP_FORCE_PD_POWERDOWN BIT(14)
+#define UTMIP_FORCE_PD2_POWERDOWN BIT(16)
+#define UTMIP_FORCE_PDZI_POWERDOWN BIT(18)
+#define UTMIP_XCVR_LSBIAS_SEL BIT(21)
#define UTMIP_XCVR_HSSLEW(x) (((x) & 0x3) << 4)
#define UTMIP_XCVR_HSSLEW_MSB(x) ((((x) & 0x1fc) >> 2) << 25)
-#define UTMIP_BIAS_CFG0 0x80c
-#define UTMIP_OTGPD (1 << 11)
-#define UTMIP_BIASPD (1 << 10)
-#define UTMIP_HSSQUELCH_LEVEL(x) (((x) & 0x3) << 0)
-#define UTMIP_HSDISCON_LEVEL(x) (((x) & 0x3) << 2)
-#define UTMIP_HSDISCON_LEVEL_MSB(x) ((((x) & 0x4) >> 2) << 24)
+#define UTMIP_BIAS_CFG0 0x80c
+#define UTMIP_OTGPD BIT(11)
+#define UTMIP_BIASPD BIT(10)
+#define UTMIP_HSSQUELCH_LEVEL(x) (((x) & 0x3) << 0)
+#define UTMIP_HSDISCON_LEVEL(x) (((x) & 0x3) << 2)
+#define UTMIP_HSDISCON_LEVEL_MSB(x) ((((x) & 0x4) >> 2) << 24)
-#define UTMIP_HSRX_CFG0 0x810
-#define UTMIP_ELASTIC_LIMIT(x) (((x) & 0x1f) << 10)
-#define UTMIP_IDLE_WAIT(x) (((x) & 0x1f) << 15)
+#define UTMIP_HSRX_CFG0 0x810
+#define UTMIP_ELASTIC_LIMIT(x) (((x) & 0x1f) << 10)
+#define UTMIP_IDLE_WAIT(x) (((x) & 0x1f) << 15)
-#define UTMIP_HSRX_CFG1 0x814
-#define UTMIP_HS_SYNC_START_DLY(x) (((x) & 0x1f) << 1)
+#define UTMIP_HSRX_CFG1 0x814
+#define UTMIP_HS_SYNC_START_DLY(x) (((x) & 0x1f) << 1)
-#define UTMIP_TX_CFG0 0x820
-#define UTMIP_FS_PREABMLE_J (1 << 19)
-#define UTMIP_HS_DISCON_DISABLE (1 << 8)
+#define UTMIP_TX_CFG0 0x820
+#define UTMIP_FS_PREABMLE_J BIT(19)
+#define UTMIP_HS_DISCON_DISABLE BIT(8)
-#define UTMIP_MISC_CFG0 0x824
-#define UTMIP_DPDM_OBSERVE (1 << 26)
-#define UTMIP_DPDM_OBSERVE_SEL(x) (((x) & 0xf) << 27)
-#define UTMIP_DPDM_OBSERVE_SEL_FS_J UTMIP_DPDM_OBSERVE_SEL(0xf)
-#define UTMIP_DPDM_OBSERVE_SEL_FS_K UTMIP_DPDM_OBSERVE_SEL(0xe)
-#define UTMIP_DPDM_OBSERVE_SEL_FS_SE1 UTMIP_DPDM_OBSERVE_SEL(0xd)
-#define UTMIP_DPDM_OBSERVE_SEL_FS_SE0 UTMIP_DPDM_OBSERVE_SEL(0xc)
-#define UTMIP_SUSPEND_EXIT_ON_EDGE (1 << 22)
+#define UTMIP_MISC_CFG0 0x824
+#define UTMIP_DPDM_OBSERVE BIT(26)
+#define UTMIP_DPDM_OBSERVE_SEL(x) (((x) & 0xf) << 27)
+#define UTMIP_DPDM_OBSERVE_SEL_FS_J UTMIP_DPDM_OBSERVE_SEL(0xf)
+#define UTMIP_DPDM_OBSERVE_SEL_FS_K UTMIP_DPDM_OBSERVE_SEL(0xe)
+#define UTMIP_DPDM_OBSERVE_SEL_FS_SE1 UTMIP_DPDM_OBSERVE_SEL(0xd)
+#define UTMIP_DPDM_OBSERVE_SEL_FS_SE0 UTMIP_DPDM_OBSERVE_SEL(0xc)
+#define UTMIP_SUSPEND_EXIT_ON_EDGE BIT(22)
-#define UTMIP_MISC_CFG1 0x828
-#define UTMIP_PLL_ACTIVE_DLY_COUNT(x) (((x) & 0x1f) << 18)
-#define UTMIP_PLLU_STABLE_COUNT(x) (((x) & 0xfff) << 6)
+#define UTMIP_MISC_CFG1 0x828
+#define UTMIP_PLL_ACTIVE_DLY_COUNT(x) (((x) & 0x1f) << 18)
+#define UTMIP_PLLU_STABLE_COUNT(x) (((x) & 0xfff) << 6)
-#define UTMIP_DEBOUNCE_CFG0 0x82c
-#define UTMIP_BIAS_DEBOUNCE_A(x) (((x) & 0xffff) << 0)
+#define UTMIP_DEBOUNCE_CFG0 0x82c
+#define UTMIP_BIAS_DEBOUNCE_A(x) (((x) & 0xffff) << 0)
-#define UTMIP_BAT_CHRG_CFG0 0x830
-#define UTMIP_PD_CHRG (1 << 0)
+#define UTMIP_BAT_CHRG_CFG0 0x830
+#define UTMIP_PD_CHRG BIT(0)
-#define UTMIP_SPARE_CFG0 0x834
-#define FUSE_SETUP_SEL (1 << 3)
+#define UTMIP_SPARE_CFG0 0x834
+#define FUSE_SETUP_SEL BIT(3)
-#define UTMIP_XCVR_CFG1 0x838
-#define UTMIP_FORCE_PDDISC_POWERDOWN (1 << 0)
-#define UTMIP_FORCE_PDCHRP_POWERDOWN (1 << 2)
-#define UTMIP_FORCE_PDDR_POWERDOWN (1 << 4)
-#define UTMIP_XCVR_TERM_RANGE_ADJ(x) (((x) & 0xf) << 18)
+#define UTMIP_XCVR_CFG1 0x838
+#define UTMIP_FORCE_PDDISC_POWERDOWN BIT(0)
+#define UTMIP_FORCE_PDCHRP_POWERDOWN BIT(2)
+#define UTMIP_FORCE_PDDR_POWERDOWN BIT(4)
+#define UTMIP_XCVR_TERM_RANGE_ADJ(x) (((x) & 0xf) << 18)
-#define UTMIP_BIAS_CFG1 0x83c
-#define UTMIP_BIAS_PDTRK_COUNT(x) (((x) & 0x1f) << 3)
+#define UTMIP_BIAS_CFG1 0x83c
+#define UTMIP_BIAS_PDTRK_COUNT(x) (((x) & 0x1f) << 3)
/* For Tegra30 and above only, the address is different in Tegra20 */
-#define USB_USBMODE 0x1f8
-#define USB_USBMODE_MASK (3 << 0)
-#define USB_USBMODE_HOST (3 << 0)
-#define USB_USBMODE_DEVICE (2 << 0)
+#define USB_USBMODE 0x1f8
+#define USB_USBMODE_MASK (3 << 0)
+#define USB_USBMODE_HOST (3 << 0)
+#define USB_USBMODE_DEVICE (2 << 0)
static DEFINE_SPINLOCK(utmip_pad_lock);
-static int utmip_pad_count;
+static unsigned int utmip_pad_count;
struct tegra_xtal_freq {
- int freq;
+ unsigned int freq;
u8 enable_delay;
u8 stable_count;
u8 active_delay;
@@ -194,6 +194,11 @@ static const struct tegra_xtal_freq tegra_freq_table[] = {
},
};
+static inline struct tegra_usb_phy *to_tegra_usb_phy(struct usb_phy *u_phy)
+{
+ return container_of(u_phy, struct tegra_usb_phy, u_phy);
+}
+
static void set_pts(struct tegra_usb_phy *phy, u8 pts_val)
{
void __iomem *base = phy->regs;
@@ -298,13 +303,16 @@ static int utmip_pad_close(struct tegra_usb_phy *phy)
return ret;
}
-static void utmip_pad_power_on(struct tegra_usb_phy *phy)
+static int utmip_pad_power_on(struct tegra_usb_phy *phy)
{
- unsigned long val, flags;
- void __iomem *base = phy->pad_regs;
struct tegra_utmip_config *config = phy->config;
+ void __iomem *base = phy->pad_regs;
+ unsigned long val, flags;
+ int err;
- clk_prepare_enable(phy->pad_clk);
+ err = clk_prepare_enable(phy->pad_clk);
+ if (err)
+ return err;
spin_lock_irqsave(&utmip_pad_lock, flags);
@@ -327,19 +335,24 @@ static void utmip_pad_power_on(struct tegra_usb_phy *phy)
spin_unlock_irqrestore(&utmip_pad_lock, flags);
clk_disable_unprepare(phy->pad_clk);
+
+ return 0;
}
static int utmip_pad_power_off(struct tegra_usb_phy *phy)
{
- unsigned long val, flags;
void __iomem *base = phy->pad_regs;
+ unsigned long val, flags;
+ int err;
if (!utmip_pad_count) {
dev_err(phy->u_phy.dev, "UTMIP pad already powered off\n");
return -EINVAL;
}
- clk_prepare_enable(phy->pad_clk);
+ err = clk_prepare_enable(phy->pad_clk);
+ if (err)
+ return err;
spin_lock_irqsave(&utmip_pad_lock, flags);
@@ -366,8 +379,8 @@ static int utmi_wait_register(void __iomem *reg, u32 mask, u32 result)
static void utmi_phy_clk_disable(struct tegra_usb_phy *phy)
{
- unsigned long val;
void __iomem *base = phy->regs;
+ unsigned long val;
/*
* The USB driver may have already initiated the phy clock
@@ -382,23 +395,24 @@ static void utmi_phy_clk_disable(struct tegra_usb_phy *phy)
val |= USB_SUSP_SET;
writel(val, base + USB_SUSP_CTRL);
- udelay(10);
+ usleep_range(10, 100);
val = readl(base + USB_SUSP_CTRL);
val &= ~USB_SUSP_SET;
writel(val, base + USB_SUSP_CTRL);
- } else
+ } else {
set_phcd(phy, true);
+ }
- if (utmi_wait_register(base + USB_SUSP_CTRL, USB_PHY_CLK_VALID, 0) < 0)
+ if (utmi_wait_register(base + USB_SUSP_CTRL, USB_PHY_CLK_VALID, 0))
dev_err(phy->u_phy.dev,
"Timeout waiting for PHY to stabilize on disable\n");
}
static void utmi_phy_clk_enable(struct tegra_usb_phy *phy)
{
- unsigned long val;
void __iomem *base = phy->regs;
+ unsigned long val;
/*
* The USB driver may have already initiated the phy clock
@@ -414,25 +428,27 @@ static void utmi_phy_clk_enable(struct tegra_usb_phy *phy)
val |= USB_SUSP_CLR;
writel(val, base + USB_SUSP_CTRL);
- udelay(10);
+ usleep_range(10, 100);
val = readl(base + USB_SUSP_CTRL);
val &= ~USB_SUSP_CLR;
writel(val, base + USB_SUSP_CTRL);
- } else
+ } else {
set_phcd(phy, false);
+ }
if (utmi_wait_register(base + USB_SUSP_CTRL, USB_PHY_CLK_VALID,
- USB_PHY_CLK_VALID))
+ USB_PHY_CLK_VALID))
dev_err(phy->u_phy.dev,
"Timeout waiting for PHY to stabilize on enable\n");
}
static int utmi_phy_power_on(struct tegra_usb_phy *phy)
{
- unsigned long val;
- void __iomem *base = phy->regs;
struct tegra_utmip_config *config = phy->config;
+ void __iomem *base = phy->regs;
+ unsigned long val;
+ int err;
val = readl(base + USB_SUSP_CTRL);
val |= UTMIP_RESET;
@@ -498,7 +514,9 @@ static int utmi_phy_power_on(struct tegra_usb_phy *phy)
writel(val, base + UTMIP_BAT_CHRG_CFG0);
}
- utmip_pad_power_on(phy);
+ err = utmip_pad_power_on(phy);
+ if (err)
+ return err;
val = readl(base + UTMIP_XCVR_CFG0);
val &= ~(UTMIP_FORCE_PD_POWERDOWN | UTMIP_FORCE_PD2_POWERDOWN |
@@ -579,8 +597,8 @@ static int utmi_phy_power_on(struct tegra_usb_phy *phy)
static int utmi_phy_power_off(struct tegra_usb_phy *phy)
{
- unsigned long val;
void __iomem *base = phy->regs;
+ unsigned long val;
utmi_phy_clk_disable(phy);
@@ -614,8 +632,8 @@ static int utmi_phy_power_off(struct tegra_usb_phy *phy)
static void utmi_phy_preresume(struct tegra_usb_phy *phy)
{
- unsigned long val;
void __iomem *base = phy->regs;
+ unsigned long val;
val = readl(base + UTMIP_TX_CFG0);
val |= UTMIP_HS_DISCON_DISABLE;
@@ -624,8 +642,8 @@ static void utmi_phy_preresume(struct tegra_usb_phy *phy)
static void utmi_phy_postresume(struct tegra_usb_phy *phy)
{
- unsigned long val;
void __iomem *base = phy->regs;
+ unsigned long val;
val = readl(base + UTMIP_TX_CFG0);
val &= ~UTMIP_HS_DISCON_DISABLE;
@@ -635,8 +653,8 @@ static void utmi_phy_postresume(struct tegra_usb_phy *phy)
static void utmi_phy_restore_start(struct tegra_usb_phy *phy,
enum tegra_usb_phy_port_speed port_speed)
{
- unsigned long val;
void __iomem *base = phy->regs;
+ unsigned long val;
val = readl(base + UTMIP_MISC_CFG0);
val &= ~UTMIP_DPDM_OBSERVE_SEL(~0);
@@ -645,47 +663,52 @@ static void utmi_phy_restore_start(struct tegra_usb_phy *phy,
else
val |= UTMIP_DPDM_OBSERVE_SEL_FS_J;
writel(val, base + UTMIP_MISC_CFG0);
- udelay(1);
+ usleep_range(1, 10);
val = readl(base + UTMIP_MISC_CFG0);
val |= UTMIP_DPDM_OBSERVE;
writel(val, base + UTMIP_MISC_CFG0);
- udelay(10);
+ usleep_range(10, 100);
}
static void utmi_phy_restore_end(struct tegra_usb_phy *phy)
{
- unsigned long val;
void __iomem *base = phy->regs;
+ unsigned long val;
val = readl(base + UTMIP_MISC_CFG0);
val &= ~UTMIP_DPDM_OBSERVE;
writel(val, base + UTMIP_MISC_CFG0);
- udelay(10);
+ usleep_range(10, 100);
}
static int ulpi_phy_power_on(struct tegra_usb_phy *phy)
{
- int ret;
- unsigned long val;
void __iomem *base = phy->regs;
+ unsigned long val;
+ int err;
- ret = gpio_direction_output(phy->reset_gpio, 0);
- if (ret < 0) {
+ err = gpio_direction_output(phy->reset_gpio, 0);
+ if (err) {
dev_err(phy->u_phy.dev, "GPIO %d not set to 0: %d\n",
- phy->reset_gpio, ret);
- return ret;
+ phy->reset_gpio, err);
+ return err;
}
- msleep(5);
- ret = gpio_direction_output(phy->reset_gpio, 1);
- if (ret < 0) {
+
+ err = clk_prepare_enable(phy->clk);
+ if (err)
+ return err;
+
+ usleep_range(5000, 6000);
+
+ err = gpio_direction_output(phy->reset_gpio, 1);
+ if (err) {
dev_err(phy->u_phy.dev, "GPIO %d not set to 1: %d\n",
- phy->reset_gpio, ret);
- return ret;
+ phy->reset_gpio, err);
+ goto disable_clk;
}
- clk_prepare_enable(phy->clk);
- msleep(1);
+ usleep_range(1000, 2000);
val = readl(base + USB_SUSP_CTRL);
val |= UHSIC_RESET;
@@ -706,7 +729,7 @@ static int ulpi_phy_power_on(struct tegra_usb_phy *phy)
val |= ULPI_STPDIRNXT_TRIMMER_SEL(4);
val |= ULPI_DIR_TRIMMER_SEL(4);
writel(val, base + ULPI_TIMING_CTRL_1);
- udelay(10);
+ usleep_range(10, 100);
val |= ULPI_DATA_TRIMMER_LOAD;
val |= ULPI_STPDIRNXT_TRIMMER_LOAD;
@@ -714,28 +737,33 @@ static int ulpi_phy_power_on(struct tegra_usb_phy *phy)
writel(val, base + ULPI_TIMING_CTRL_1);
/* Fix VbusInvalid due to floating VBUS */
- ret = usb_phy_io_write(phy->ulpi, 0x40, 0x08);
- if (ret) {
- dev_err(phy->u_phy.dev, "ULPI write failed: %d\n", ret);
- return ret;
+ err = usb_phy_io_write(phy->ulpi, 0x40, 0x08);
+ if (err) {
+ dev_err(phy->u_phy.dev, "ULPI write failed: %d\n", err);
+ goto disable_clk;
}
- ret = usb_phy_io_write(phy->ulpi, 0x80, 0x0B);
- if (ret) {
- dev_err(phy->u_phy.dev, "ULPI write failed: %d\n", ret);
- return ret;
+ err = usb_phy_io_write(phy->ulpi, 0x80, 0x0B);
+ if (err) {
+ dev_err(phy->u_phy.dev, "ULPI write failed: %d\n", err);
+ goto disable_clk;
}
val = readl(base + USB_SUSP_CTRL);
val |= USB_SUSP_CLR;
writel(val, base + USB_SUSP_CTRL);
- udelay(100);
+ usleep_range(100, 1000);
val = readl(base + USB_SUSP_CTRL);
val &= ~USB_SUSP_CLR;
writel(val, base + USB_SUSP_CTRL);
return 0;
+
+disable_clk:
+ clk_disable_unprepare(phy->clk);
+
+ return err;
}
static int ulpi_phy_power_off(struct tegra_usb_phy *phy)
@@ -795,8 +823,7 @@ static int tegra_usb_phy_power_off(struct tegra_usb_phy *phy)
static void tegra_usb_phy_shutdown(struct usb_phy *u_phy)
{
- struct tegra_usb_phy *phy = container_of(u_phy, struct tegra_usb_phy,
- u_phy);
+ struct tegra_usb_phy *phy = to_tegra_usb_phy(u_phy);
if (WARN_ON(!phy->freq))
return;
@@ -814,9 +841,9 @@ static void tegra_usb_phy_shutdown(struct usb_phy *u_phy)
phy->freq = NULL;
}
-static int tegra_usb_phy_set_suspend(struct usb_phy *x, int suspend)
+static int tegra_usb_phy_set_suspend(struct usb_phy *u_phy, int suspend)
{
- struct tegra_usb_phy *phy = container_of(x, struct tegra_usb_phy, u_phy);
+ struct tegra_usb_phy *phy = to_tegra_usb_phy(u_phy);
if (WARN_ON(!phy->freq))
return -EINVAL;
@@ -832,7 +859,7 @@ static int ulpi_open(struct tegra_usb_phy *phy)
int err;
err = gpio_direction_output(phy->reset_gpio, 0);
- if (err < 0) {
+ if (err) {
dev_err(phy->u_phy.dev,
"ULPI reset GPIO %d direction not asserted: %d\n",
phy->reset_gpio, err);
@@ -844,10 +871,9 @@ static int ulpi_open(struct tegra_usb_phy *phy)
static int tegra_usb_phy_init(struct usb_phy *u_phy)
{
- struct tegra_usb_phy *phy = container_of(u_phy, struct tegra_usb_phy,
- u_phy);
+ struct tegra_usb_phy *phy = to_tegra_usb_phy(u_phy);
unsigned long parent_rate;
- int i;
+ unsigned int i;
int err;
if (WARN_ON(phy->freq))
@@ -885,7 +911,7 @@ static int tegra_usb_phy_init(struct usb_phy *u_phy)
err = ulpi_open(phy);
else
err = utmip_pad_open(phy);
- if (err < 0)
+ if (err)
goto fail;
err = tegra_usb_phy_power_on(phy);
@@ -905,37 +931,37 @@ static int tegra_usb_phy_init(struct usb_phy *u_phy)
return err;
}
-void tegra_usb_phy_preresume(struct usb_phy *x)
+void tegra_usb_phy_preresume(struct usb_phy *u_phy)
{
- struct tegra_usb_phy *phy = container_of(x, struct tegra_usb_phy, u_phy);
+ struct tegra_usb_phy *phy = to_tegra_usb_phy(u_phy);
if (!phy->is_ulpi_phy)
utmi_phy_preresume(phy);
}
EXPORT_SYMBOL_GPL(tegra_usb_phy_preresume);
-void tegra_usb_phy_postresume(struct usb_phy *x)
+void tegra_usb_phy_postresume(struct usb_phy *u_phy)
{
- struct tegra_usb_phy *phy = container_of(x, struct tegra_usb_phy, u_phy);
+ struct tegra_usb_phy *phy = to_tegra_usb_phy(u_phy);
if (!phy->is_ulpi_phy)
utmi_phy_postresume(phy);
}
EXPORT_SYMBOL_GPL(tegra_usb_phy_postresume);
-void tegra_ehci_phy_restore_start(struct usb_phy *x,
- enum tegra_usb_phy_port_speed port_speed)
+void tegra_ehci_phy_restore_start(struct usb_phy *u_phy,
+ enum tegra_usb_phy_port_speed port_speed)
{
- struct tegra_usb_phy *phy = container_of(x, struct tegra_usb_phy, u_phy);
+ struct tegra_usb_phy *phy = to_tegra_usb_phy(u_phy);
if (!phy->is_ulpi_phy)
utmi_phy_restore_start(phy, port_speed);
}
EXPORT_SYMBOL_GPL(tegra_ehci_phy_restore_start);
-void tegra_ehci_phy_restore_end(struct usb_phy *x)
+void tegra_ehci_phy_restore_end(struct usb_phy *u_phy)
{
- struct tegra_usb_phy *phy = container_of(x, struct tegra_usb_phy, u_phy);
+ struct tegra_usb_phy *phy = to_tegra_usb_phy(u_phy);
if (!phy->is_ulpi_phy)
utmi_phy_restore_end(phy);
@@ -946,21 +972,25 @@ static int read_utmi_param(struct platform_device *pdev, const char *param,
u8 *dest)
{
u32 value;
- int err = of_property_read_u32(pdev->dev.of_node, param, &value);
- *dest = (u8)value;
- if (err < 0)
+ int err;
+
+ err = of_property_read_u32(pdev->dev.of_node, param, &value);
+ if (err)
dev_err(&pdev->dev,
"Failed to read USB UTMI parameter %s: %d\n",
param, err);
+ else
+ *dest = value;
+
return err;
}
static int utmi_phy_probe(struct tegra_usb_phy *tegra_phy,
struct platform_device *pdev)
{
+ struct tegra_utmip_config *config;
struct resource *res;
int err;
- struct tegra_utmip_config *config;
tegra_phy->is_ulpi_phy = false;
@@ -971,7 +1001,7 @@ static int utmi_phy_probe(struct tegra_usb_phy *tegra_phy,
}
tegra_phy->pad_regs = devm_ioremap(&pdev->dev, res->start,
- resource_size(res));
+ resource_size(res));
if (!tegra_phy->pad_regs) {
dev_err(&pdev->dev, "Failed to remap UTMI pad regs\n");
return -ENOMEM;
@@ -985,49 +1015,49 @@ static int utmi_phy_probe(struct tegra_usb_phy *tegra_phy,
config = tegra_phy->config;
err = read_utmi_param(pdev, "nvidia,hssync-start-delay",
- &config->hssync_start_delay);
- if (err < 0)
+ &config->hssync_start_delay);
+ if (err)
return err;
err = read_utmi_param(pdev, "nvidia,elastic-limit",
- &config->elastic_limit);
- if (err < 0)
+ &config->elastic_limit);
+ if (err)
return err;
err = read_utmi_param(pdev, "nvidia,idle-wait-delay",
- &config->idle_wait_delay);
- if (err < 0)
+ &config->idle_wait_delay);
+ if (err)
return err;
err = read_utmi_param(pdev, "nvidia,term-range-adj",
- &config->term_range_adj);
- if (err < 0)
+ &config->term_range_adj);
+ if (err)
return err;
err = read_utmi_param(pdev, "nvidia,xcvr-lsfslew",
- &config->xcvr_lsfslew);
- if (err < 0)
+ &config->xcvr_lsfslew);
+ if (err)
return err;
err = read_utmi_param(pdev, "nvidia,xcvr-lsrslew",
- &config->xcvr_lsrslew);
- if (err < 0)
+ &config->xcvr_lsrslew);
+ if (err)
return err;
if (tegra_phy->soc_config->requires_extra_tuning_parameters) {
err = read_utmi_param(pdev, "nvidia,xcvr-hsslew",
- &config->xcvr_hsslew);
- if (err < 0)
+ &config->xcvr_hsslew);
+ if (err)
return err;
err = read_utmi_param(pdev, "nvidia,hssquelch-level",
- &config->hssquelch_level);
- if (err < 0)
+ &config->hssquelch_level);
+ if (err)
return err;
err = read_utmi_param(pdev, "nvidia,hsdiscon-level",
- &config->hsdiscon_level);
- if (err < 0)
+ &config->hsdiscon_level);
+ if (err)
return err;
}
@@ -1036,8 +1066,8 @@ static int utmi_phy_probe(struct tegra_usb_phy *tegra_phy,
if (!config->xcvr_setup_use_fuses) {
err = read_utmi_param(pdev, "nvidia,xcvr-setup",
- &config->xcvr_setup);
- if (err < 0)
+ &config->xcvr_setup);
+ if (err)
return err;
}
@@ -1067,23 +1097,18 @@ MODULE_DEVICE_TABLE(of, tegra_usb_phy_id_table);
static int tegra_usb_phy_probe(struct platform_device *pdev)
{
- const struct of_device_id *match;
- struct resource *res;
- struct tegra_usb_phy *tegra_phy = NULL;
struct device_node *np = pdev->dev.of_node;
+ struct tegra_usb_phy *tegra_phy;
enum usb_phy_interface phy_type;
+ struct reset_control *reset;
+ struct resource *res;
int err;
tegra_phy = devm_kzalloc(&pdev->dev, sizeof(*tegra_phy), GFP_KERNEL);
if (!tegra_phy)
return -ENOMEM;
- match = of_match_device(tegra_usb_phy_id_table, &pdev->dev);
- if (!match) {
- dev_err(&pdev->dev, "Error: No device match found\n");
- return -ENODEV;
- }
- tegra_phy->soc_config = match->data;
+ tegra_phy->soc_config = of_device_get_match_data(&pdev->dev);
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res) {
@@ -1092,7 +1117,7 @@ static int tegra_usb_phy_probe(struct platform_device *pdev)
}
tegra_phy->regs = devm_ioremap(&pdev->dev, res->start,
- resource_size(res));
+ resource_size(res));
if (!tegra_phy->regs) {
dev_err(&pdev->dev, "Failed to remap I/O memory\n");
return -ENOMEM;
@@ -1101,33 +1126,6 @@ static int tegra_usb_phy_probe(struct platform_device *pdev)
tegra_phy->is_legacy_phy =
of_property_read_bool(np, "nvidia,has-legacy-mode");
- phy_type = of_usb_get_phy_mode(np);
- switch (phy_type) {
- case USBPHY_INTERFACE_MODE_UTMI:
- err = utmi_phy_probe(tegra_phy, pdev);
- if (err < 0)
- return err;
- break;
-
- case USBPHY_INTERFACE_MODE_ULPI:
- tegra_phy->is_ulpi_phy = true;
-
- tegra_phy->reset_gpio =
- of_get_named_gpio(np, "nvidia,phy-reset-gpio", 0);
- if (!gpio_is_valid(tegra_phy->reset_gpio)) {
- dev_err(&pdev->dev,
- "Invalid GPIO: %d\n", tegra_phy->reset_gpio);
- return tegra_phy->reset_gpio;
- }
- tegra_phy->config = NULL;
- break;
-
- default:
- dev_err(&pdev->dev, "phy_type %u is invalid or unsupported\n",
- phy_type);
- return -EINVAL;
- }
-
if (of_find_property(np, "dr_mode", NULL))
tegra_phy->mode = usb_get_dr_mode(&pdev->dev);
else
@@ -1155,7 +1153,44 @@ static int tegra_usb_phy_probe(struct platform_device *pdev)
return err;
}
- if (tegra_phy->is_ulpi_phy) {
+ phy_type = of_usb_get_phy_mode(np);
+ switch (phy_type) {
+ case USBPHY_INTERFACE_MODE_UTMI:
+ err = utmi_phy_probe(tegra_phy, pdev);
+ if (err)
+ return err;
+
+ tegra_phy->pad_clk = devm_clk_get(&pdev->dev, "utmi-pads");
+ err = PTR_ERR_OR_ZERO(tegra_phy->pad_clk);
+ if (err) {
+ dev_err(&pdev->dev,
+ "Failed to get UTMIP pad clock: %d\n", err);
+ return err;
+ }
+
+ reset = devm_reset_control_get_optional_shared(&pdev->dev,
+ "utmi-pads");
+ err = PTR_ERR_OR_ZERO(reset);
+ if (err) {
+ dev_err(&pdev->dev,
+ "Failed to get UTMI-pads reset: %d\n", err);
+ return err;
+ }
+ tegra_phy->pad_rst = reset;
+ break;
+
+ case USBPHY_INTERFACE_MODE_ULPI:
+ tegra_phy->is_ulpi_phy = true;
+
+ tegra_phy->reset_gpio =
+ of_get_named_gpio(np, "nvidia,phy-reset-gpio", 0);
+
+ if (!gpio_is_valid(tegra_phy->reset_gpio)) {
+ dev_err(&pdev->dev,
+ "Invalid GPIO: %d\n", tegra_phy->reset_gpio);
+ return tegra_phy->reset_gpio;
+ }
+
tegra_phy->clk = devm_clk_get(&pdev->dev, "ulpi-link");
err = PTR_ERR_OR_ZERO(tegra_phy->clk);
if (err) {
@@ -1165,8 +1200,8 @@ static int tegra_usb_phy_probe(struct platform_device *pdev)
}
err = devm_gpio_request(&pdev->dev, tegra_phy->reset_gpio,
- "ulpi_phy_reset_b");
- if (err < 0) {
+ "ulpi_phy_reset_b");
+ if (err) {
dev_err(&pdev->dev, "Request failed for GPIO %d: %d\n",
tegra_phy->reset_gpio, err);
return err;
@@ -1175,28 +1210,16 @@ static int tegra_usb_phy_probe(struct platform_device *pdev)
tegra_phy->ulpi = otg_ulpi_create(&ulpi_viewport_access_ops, 0);
if (!tegra_phy->ulpi) {
dev_err(&pdev->dev, "Failed to create ULPI OTG\n");
- err = -ENOMEM;
- return err;
+ return -ENOMEM;
}
tegra_phy->ulpi->io_priv = tegra_phy->regs + ULPI_VIEWPORT;
- } else {
- tegra_phy->pad_clk = devm_clk_get(&pdev->dev, "utmi-pads");
- err = PTR_ERR_OR_ZERO(tegra_phy->pad_clk);
- if (err) {
- dev_err(&pdev->dev,
- "Failed to get UTMIP pad clock: %d\n", err);
- return err;
- }
+ break;
- tegra_phy->pad_rst = devm_reset_control_get_optional_shared(
- &pdev->dev, "utmi-pads");
- err = PTR_ERR_OR_ZERO(tegra_phy->pad_rst);
- if (err) {
- dev_err(&pdev->dev,
- "Failed to get UTMI-pads reset: %d\n", err);
- return err;
- }
+ default:
+ dev_err(&pdev->dev, "phy_type %u is invalid or unsupported\n",
+ phy_type);
+ return -EINVAL;
}
tegra_phy->u_phy.dev = &pdev->dev;
@@ -1207,7 +1230,7 @@ static int tegra_usb_phy_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, tegra_phy);
err = usb_add_phy_dev(&tegra_phy->u_phy);
- if (err < 0)
+ if (err)
goto free_ulpi;
return 0;
--
2.24.0
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCH v4 07/20] usb: phy: tegra: Clean up included headers
2020-01-06 1:33 [PATCH v4 00/20] NVIDIA Tegra USB2 drivers clean up Dmitry Osipenko
` (5 preceding siblings ...)
2020-01-06 1:34 ` [PATCH v4 06/20] usb: phy: tegra: Perform general clean up of the code Dmitry Osipenko
@ 2020-01-06 1:34 ` Dmitry Osipenko
2020-01-06 1:34 ` [PATCH v4 08/20] usb: phy: tegra: Use relaxed versions of readl/writel Dmitry Osipenko
` (12 subsequent siblings)
19 siblings, 0 replies; 23+ messages in thread
From: Dmitry Osipenko @ 2020-01-06 1:34 UTC (permalink / raw)
To: Greg Kroah-Hartman, Peter Chen, Thierry Reding, Jonathan Hunter,
Felipe Balbi, Michał Mirosław
Cc: linux-usb, linux-tegra, linux-kernel
Add "spinlock.h", which was included indirectly, and sort includes in
alphabet order.
Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
---
drivers/usb/phy/phy-tegra-usb.c | 20 +++++++++++---------
1 file changed, 11 insertions(+), 9 deletions(-)
diff --git a/drivers/usb/phy/phy-tegra-usb.c b/drivers/usb/phy/phy-tegra-usb.c
index c045f44ea964..aca1413db0ed 100644
--- a/drivers/usb/phy/phy-tegra-usb.c
+++ b/drivers/usb/phy/phy-tegra-usb.c
@@ -9,24 +9,26 @@
* Venu Byravarasu <vbyravarasu@nvidia.com>
*/
-#include <linux/resource.h>
#include <linux/delay.h>
-#include <linux/slab.h>
#include <linux/err.h>
#include <linux/export.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/iopoll.h>
#include <linux/gpio.h>
+#include <linux/iopoll.h>
+#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/of_gpio.h>
-#include <linux/usb/otg.h>
-#include <linux/usb/ulpi.h>
-#include <linux/usb/of.h>
+#include <linux/platform_device.h>
+#include <linux/resource.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+
+#include <linux/regulator/consumer.h>
+
#include <linux/usb/ehci_def.h>
+#include <linux/usb/of.h>
#include <linux/usb/tegra_usb_phy.h>
-#include <linux/regulator/consumer.h>
+#include <linux/usb/ulpi.h>
#define ULPI_VIEWPORT 0x170
--
2.24.0
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCH v4 08/20] usb: phy: tegra: Use relaxed versions of readl/writel
2020-01-06 1:33 [PATCH v4 00/20] NVIDIA Tegra USB2 drivers clean up Dmitry Osipenko
` (6 preceding siblings ...)
2020-01-06 1:34 ` [PATCH v4 07/20] usb: phy: tegra: Clean up included headers Dmitry Osipenko
@ 2020-01-06 1:34 ` Dmitry Osipenko
2020-01-06 1:34 ` [PATCH v4 09/20] usb: phy: tegra: Use generic stub for a missing VBUS regulator Dmitry Osipenko
` (11 subsequent siblings)
19 siblings, 0 replies; 23+ messages in thread
From: Dmitry Osipenko @ 2020-01-06 1:34 UTC (permalink / raw)
To: Greg Kroah-Hartman, Peter Chen, Thierry Reding, Jonathan Hunter,
Felipe Balbi, Michał Mirosław
Cc: linux-usb, linux-tegra, linux-kernel
There is nothing to synchronize in regards to memory stores, thus all
readl/writel occurrences in the code could be replaced with a relaxed
versions, for consistency.
Acked-by: Thierry Reding <treding@nvidia.com>
Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
---
drivers/usb/phy/phy-tegra-usb.c | 195 ++++++++++++++++----------------
1 file changed, 98 insertions(+), 97 deletions(-)
diff --git a/drivers/usb/phy/phy-tegra-usb.c b/drivers/usb/phy/phy-tegra-usb.c
index aca1413db0ed..268b9d9ce57e 100644
--- a/drivers/usb/phy/phy-tegra-usb.c
+++ b/drivers/usb/phy/phy-tegra-usb.c
@@ -207,15 +207,16 @@ static void set_pts(struct tegra_usb_phy *phy, u8 pts_val)
unsigned long val;
if (phy->soc_config->has_hostpc) {
- val = readl(base + TEGRA_USB_HOSTPC1_DEVLC);
+ val = readl_relaxed(base + TEGRA_USB_HOSTPC1_DEVLC);
val &= ~TEGRA_USB_HOSTPC1_DEVLC_PTS(~0);
val |= TEGRA_USB_HOSTPC1_DEVLC_PTS(pts_val);
- writel(val, base + TEGRA_USB_HOSTPC1_DEVLC);
+ writel_relaxed(val, base + TEGRA_USB_HOSTPC1_DEVLC);
} else {
- val = readl(base + TEGRA_USB_PORTSC1) & ~TEGRA_PORTSC1_RWC_BITS;
+ val = readl_relaxed(base + TEGRA_USB_PORTSC1);
+ val &= ~TEGRA_PORTSC1_RWC_BITS;
val &= ~TEGRA_USB_PORTSC1_PTS(~0);
val |= TEGRA_USB_PORTSC1_PTS(pts_val);
- writel(val, base + TEGRA_USB_PORTSC1);
+ writel_relaxed(val, base + TEGRA_USB_PORTSC1);
}
}
@@ -225,19 +226,19 @@ static void set_phcd(struct tegra_usb_phy *phy, bool enable)
unsigned long val;
if (phy->soc_config->has_hostpc) {
- val = readl(base + TEGRA_USB_HOSTPC1_DEVLC);
+ val = readl_relaxed(base + TEGRA_USB_HOSTPC1_DEVLC);
if (enable)
val |= TEGRA_USB_HOSTPC1_DEVLC_PHCD;
else
val &= ~TEGRA_USB_HOSTPC1_DEVLC_PHCD;
- writel(val, base + TEGRA_USB_HOSTPC1_DEVLC);
+ writel_relaxed(val, base + TEGRA_USB_HOSTPC1_DEVLC);
} else {
- val = readl(base + TEGRA_USB_PORTSC1) & ~PORT_RWC_BITS;
+ val = readl_relaxed(base + TEGRA_USB_PORTSC1) & ~PORT_RWC_BITS;
if (enable)
val |= TEGRA_USB_PORTSC1_PHCD;
else
val &= ~TEGRA_USB_PORTSC1_PHCD;
- writel(val, base + TEGRA_USB_PORTSC1);
+ writel_relaxed(val, base + TEGRA_USB_PORTSC1);
}
}
@@ -319,7 +320,7 @@ static int utmip_pad_power_on(struct tegra_usb_phy *phy)
spin_lock_irqsave(&utmip_pad_lock, flags);
if (utmip_pad_count++ == 0) {
- val = readl(base + UTMIP_BIAS_CFG0);
+ val = readl_relaxed(base + UTMIP_BIAS_CFG0);
val &= ~(UTMIP_OTGPD | UTMIP_BIASPD);
if (phy->soc_config->requires_extra_tuning_parameters) {
@@ -331,7 +332,7 @@ static int utmip_pad_power_on(struct tegra_usb_phy *phy)
val |= UTMIP_HSDISCON_LEVEL(config->hsdiscon_level);
val |= UTMIP_HSDISCON_LEVEL_MSB(config->hsdiscon_level);
}
- writel(val, base + UTMIP_BIAS_CFG0);
+ writel_relaxed(val, base + UTMIP_BIAS_CFG0);
}
spin_unlock_irqrestore(&utmip_pad_lock, flags);
@@ -359,9 +360,9 @@ static int utmip_pad_power_off(struct tegra_usb_phy *phy)
spin_lock_irqsave(&utmip_pad_lock, flags);
if (--utmip_pad_count == 0) {
- val = readl(base + UTMIP_BIAS_CFG0);
+ val = readl_relaxed(base + UTMIP_BIAS_CFG0);
val |= UTMIP_OTGPD | UTMIP_BIASPD;
- writel(val, base + UTMIP_BIAS_CFG0);
+ writel_relaxed(val, base + UTMIP_BIAS_CFG0);
}
spin_unlock_irqrestore(&utmip_pad_lock, flags);
@@ -375,8 +376,8 @@ static int utmi_wait_register(void __iomem *reg, u32 mask, u32 result)
{
u32 tmp;
- return readl_poll_timeout(reg, tmp, (tmp & mask) == result,
- 2000, 6000);
+ return readl_relaxed_poll_timeout(reg, tmp, (tmp & mask) == result,
+ 2000, 6000);
}
static void utmi_phy_clk_disable(struct tegra_usb_phy *phy)
@@ -393,15 +394,15 @@ static void utmi_phy_clk_disable(struct tegra_usb_phy *phy)
return;
if (phy->is_legacy_phy) {
- val = readl(base + USB_SUSP_CTRL);
+ val = readl_relaxed(base + USB_SUSP_CTRL);
val |= USB_SUSP_SET;
- writel(val, base + USB_SUSP_CTRL);
+ writel_relaxed(val, base + USB_SUSP_CTRL);
usleep_range(10, 100);
- val = readl(base + USB_SUSP_CTRL);
+ val = readl_relaxed(base + USB_SUSP_CTRL);
val &= ~USB_SUSP_SET;
- writel(val, base + USB_SUSP_CTRL);
+ writel_relaxed(val, base + USB_SUSP_CTRL);
} else {
set_phcd(phy, true);
}
@@ -426,15 +427,15 @@ static void utmi_phy_clk_enable(struct tegra_usb_phy *phy)
return;
if (phy->is_legacy_phy) {
- val = readl(base + USB_SUSP_CTRL);
+ val = readl_relaxed(base + USB_SUSP_CTRL);
val |= USB_SUSP_CLR;
- writel(val, base + USB_SUSP_CTRL);
+ writel_relaxed(val, base + USB_SUSP_CTRL);
usleep_range(10, 100);
- val = readl(base + USB_SUSP_CTRL);
+ val = readl_relaxed(base + USB_SUSP_CTRL);
val &= ~USB_SUSP_CLR;
- writel(val, base + USB_SUSP_CTRL);
+ writel_relaxed(val, base + USB_SUSP_CTRL);
} else {
set_phcd(phy, false);
}
@@ -452,75 +453,75 @@ static int utmi_phy_power_on(struct tegra_usb_phy *phy)
unsigned long val;
int err;
- val = readl(base + USB_SUSP_CTRL);
+ val = readl_relaxed(base + USB_SUSP_CTRL);
val |= UTMIP_RESET;
- writel(val, base + USB_SUSP_CTRL);
+ writel_relaxed(val, base + USB_SUSP_CTRL);
if (phy->is_legacy_phy) {
- val = readl(base + USB1_LEGACY_CTRL);
+ val = readl_relaxed(base + USB1_LEGACY_CTRL);
val |= USB1_NO_LEGACY_MODE;
- writel(val, base + USB1_LEGACY_CTRL);
+ writel_relaxed(val, base + USB1_LEGACY_CTRL);
}
- val = readl(base + UTMIP_TX_CFG0);
+ val = readl_relaxed(base + UTMIP_TX_CFG0);
val |= UTMIP_FS_PREABMLE_J;
- writel(val, base + UTMIP_TX_CFG0);
+ writel_relaxed(val, base + UTMIP_TX_CFG0);
- val = readl(base + UTMIP_HSRX_CFG0);
+ val = readl_relaxed(base + UTMIP_HSRX_CFG0);
val &= ~(UTMIP_IDLE_WAIT(~0) | UTMIP_ELASTIC_LIMIT(~0));
val |= UTMIP_IDLE_WAIT(config->idle_wait_delay);
val |= UTMIP_ELASTIC_LIMIT(config->elastic_limit);
- writel(val, base + UTMIP_HSRX_CFG0);
+ writel_relaxed(val, base + UTMIP_HSRX_CFG0);
- val = readl(base + UTMIP_HSRX_CFG1);
+ val = readl_relaxed(base + UTMIP_HSRX_CFG1);
val &= ~UTMIP_HS_SYNC_START_DLY(~0);
val |= UTMIP_HS_SYNC_START_DLY(config->hssync_start_delay);
- writel(val, base + UTMIP_HSRX_CFG1);
+ writel_relaxed(val, base + UTMIP_HSRX_CFG1);
- val = readl(base + UTMIP_DEBOUNCE_CFG0);
+ val = readl_relaxed(base + UTMIP_DEBOUNCE_CFG0);
val &= ~UTMIP_BIAS_DEBOUNCE_A(~0);
val |= UTMIP_BIAS_DEBOUNCE_A(phy->freq->debounce);
- writel(val, base + UTMIP_DEBOUNCE_CFG0);
+ writel_relaxed(val, base + UTMIP_DEBOUNCE_CFG0);
- val = readl(base + UTMIP_MISC_CFG0);
+ val = readl_relaxed(base + UTMIP_MISC_CFG0);
val &= ~UTMIP_SUSPEND_EXIT_ON_EDGE;
- writel(val, base + UTMIP_MISC_CFG0);
+ writel_relaxed(val, base + UTMIP_MISC_CFG0);
if (!phy->soc_config->utmi_pll_config_in_car_module) {
- val = readl(base + UTMIP_MISC_CFG1);
+ val = readl_relaxed(base + UTMIP_MISC_CFG1);
val &= ~(UTMIP_PLL_ACTIVE_DLY_COUNT(~0) |
UTMIP_PLLU_STABLE_COUNT(~0));
val |= UTMIP_PLL_ACTIVE_DLY_COUNT(phy->freq->active_delay) |
UTMIP_PLLU_STABLE_COUNT(phy->freq->stable_count);
- writel(val, base + UTMIP_MISC_CFG1);
+ writel_relaxed(val, base + UTMIP_MISC_CFG1);
- val = readl(base + UTMIP_PLL_CFG1);
+ val = readl_relaxed(base + UTMIP_PLL_CFG1);
val &= ~(UTMIP_XTAL_FREQ_COUNT(~0) |
UTMIP_PLLU_ENABLE_DLY_COUNT(~0));
val |= UTMIP_XTAL_FREQ_COUNT(phy->freq->xtal_freq_count) |
UTMIP_PLLU_ENABLE_DLY_COUNT(phy->freq->enable_delay);
- writel(val, base + UTMIP_PLL_CFG1);
+ writel_relaxed(val, base + UTMIP_PLL_CFG1);
}
if (phy->mode == USB_DR_MODE_PERIPHERAL) {
- val = readl(base + USB_SUSP_CTRL);
+ val = readl_relaxed(base + USB_SUSP_CTRL);
val &= ~(USB_WAKE_ON_CNNT_EN_DEV | USB_WAKE_ON_DISCON_EN_DEV);
- writel(val, base + USB_SUSP_CTRL);
+ writel_relaxed(val, base + USB_SUSP_CTRL);
- val = readl(base + UTMIP_BAT_CHRG_CFG0);
+ val = readl_relaxed(base + UTMIP_BAT_CHRG_CFG0);
val &= ~UTMIP_PD_CHRG;
- writel(val, base + UTMIP_BAT_CHRG_CFG0);
+ writel_relaxed(val, base + UTMIP_BAT_CHRG_CFG0);
} else {
- val = readl(base + UTMIP_BAT_CHRG_CFG0);
+ val = readl_relaxed(base + UTMIP_BAT_CHRG_CFG0);
val |= UTMIP_PD_CHRG;
- writel(val, base + UTMIP_BAT_CHRG_CFG0);
+ writel_relaxed(val, base + UTMIP_BAT_CHRG_CFG0);
}
err = utmip_pad_power_on(phy);
if (err)
return err;
- val = readl(base + UTMIP_XCVR_CFG0);
+ val = readl_relaxed(base + UTMIP_XCVR_CFG0);
val &= ~(UTMIP_FORCE_PD_POWERDOWN | UTMIP_FORCE_PD2_POWERDOWN |
UTMIP_FORCE_PDZI_POWERDOWN | UTMIP_XCVR_LSBIAS_SEL |
UTMIP_XCVR_SETUP(~0) | UTMIP_XCVR_SETUP_MSB(~0) |
@@ -538,57 +539,57 @@ static int utmi_phy_power_on(struct tegra_usb_phy *phy)
val |= UTMIP_XCVR_HSSLEW(config->xcvr_hsslew);
val |= UTMIP_XCVR_HSSLEW_MSB(config->xcvr_hsslew);
}
- writel(val, base + UTMIP_XCVR_CFG0);
+ writel_relaxed(val, base + UTMIP_XCVR_CFG0);
- val = readl(base + UTMIP_XCVR_CFG1);
+ val = readl_relaxed(base + UTMIP_XCVR_CFG1);
val &= ~(UTMIP_FORCE_PDDISC_POWERDOWN | UTMIP_FORCE_PDCHRP_POWERDOWN |
UTMIP_FORCE_PDDR_POWERDOWN | UTMIP_XCVR_TERM_RANGE_ADJ(~0));
val |= UTMIP_XCVR_TERM_RANGE_ADJ(config->term_range_adj);
- writel(val, base + UTMIP_XCVR_CFG1);
+ writel_relaxed(val, base + UTMIP_XCVR_CFG1);
- val = readl(base + UTMIP_BIAS_CFG1);
+ val = readl_relaxed(base + UTMIP_BIAS_CFG1);
val &= ~UTMIP_BIAS_PDTRK_COUNT(~0);
val |= UTMIP_BIAS_PDTRK_COUNT(0x5);
- writel(val, base + UTMIP_BIAS_CFG1);
+ writel_relaxed(val, base + UTMIP_BIAS_CFG1);
- val = readl(base + UTMIP_SPARE_CFG0);
+ val = readl_relaxed(base + UTMIP_SPARE_CFG0);
if (config->xcvr_setup_use_fuses)
val |= FUSE_SETUP_SEL;
else
val &= ~FUSE_SETUP_SEL;
- writel(val, base + UTMIP_SPARE_CFG0);
+ writel_relaxed(val, base + UTMIP_SPARE_CFG0);
if (!phy->is_legacy_phy) {
- val = readl(base + USB_SUSP_CTRL);
+ val = readl_relaxed(base + USB_SUSP_CTRL);
val |= UTMIP_PHY_ENABLE;
- writel(val, base + USB_SUSP_CTRL);
+ writel_relaxed(val, base + USB_SUSP_CTRL);
}
- val = readl(base + USB_SUSP_CTRL);
+ val = readl_relaxed(base + USB_SUSP_CTRL);
val &= ~UTMIP_RESET;
- writel(val, base + USB_SUSP_CTRL);
+ writel_relaxed(val, base + USB_SUSP_CTRL);
if (phy->is_legacy_phy) {
- val = readl(base + USB1_LEGACY_CTRL);
+ val = readl_relaxed(base + USB1_LEGACY_CTRL);
val &= ~USB1_VBUS_SENSE_CTL_MASK;
val |= USB1_VBUS_SENSE_CTL_A_SESS_VLD;
- writel(val, base + USB1_LEGACY_CTRL);
+ writel_relaxed(val, base + USB1_LEGACY_CTRL);
- val = readl(base + USB_SUSP_CTRL);
+ val = readl_relaxed(base + USB_SUSP_CTRL);
val &= ~USB_SUSP_SET;
- writel(val, base + USB_SUSP_CTRL);
+ writel_relaxed(val, base + USB_SUSP_CTRL);
}
utmi_phy_clk_enable(phy);
if (phy->soc_config->requires_usbmode_setup) {
- val = readl(base + USB_USBMODE);
+ val = readl_relaxed(base + USB_USBMODE);
val &= ~USB_USBMODE_MASK;
if (phy->mode == USB_DR_MODE_HOST)
val |= USB_USBMODE_HOST;
else
val |= USB_USBMODE_DEVICE;
- writel(val, base + USB_USBMODE);
+ writel_relaxed(val, base + USB_USBMODE);
}
if (!phy->is_legacy_phy)
@@ -605,29 +606,29 @@ static int utmi_phy_power_off(struct tegra_usb_phy *phy)
utmi_phy_clk_disable(phy);
if (phy->mode == USB_DR_MODE_PERIPHERAL) {
- val = readl(base + USB_SUSP_CTRL);
+ val = readl_relaxed(base + USB_SUSP_CTRL);
val &= ~USB_WAKEUP_DEBOUNCE_COUNT(~0);
val |= USB_WAKE_ON_CNNT_EN_DEV | USB_WAKEUP_DEBOUNCE_COUNT(5);
- writel(val, base + USB_SUSP_CTRL);
+ writel_relaxed(val, base + USB_SUSP_CTRL);
}
- val = readl(base + USB_SUSP_CTRL);
+ val = readl_relaxed(base + USB_SUSP_CTRL);
val |= UTMIP_RESET;
- writel(val, base + USB_SUSP_CTRL);
+ writel_relaxed(val, base + USB_SUSP_CTRL);
- val = readl(base + UTMIP_BAT_CHRG_CFG0);
+ val = readl_relaxed(base + UTMIP_BAT_CHRG_CFG0);
val |= UTMIP_PD_CHRG;
- writel(val, base + UTMIP_BAT_CHRG_CFG0);
+ writel_relaxed(val, base + UTMIP_BAT_CHRG_CFG0);
- val = readl(base + UTMIP_XCVR_CFG0);
+ val = readl_relaxed(base + UTMIP_XCVR_CFG0);
val |= UTMIP_FORCE_PD_POWERDOWN | UTMIP_FORCE_PD2_POWERDOWN |
UTMIP_FORCE_PDZI_POWERDOWN;
- writel(val, base + UTMIP_XCVR_CFG0);
+ writel_relaxed(val, base + UTMIP_XCVR_CFG0);
- val = readl(base + UTMIP_XCVR_CFG1);
+ val = readl_relaxed(base + UTMIP_XCVR_CFG1);
val |= UTMIP_FORCE_PDDISC_POWERDOWN | UTMIP_FORCE_PDCHRP_POWERDOWN |
UTMIP_FORCE_PDDR_POWERDOWN;
- writel(val, base + UTMIP_XCVR_CFG1);
+ writel_relaxed(val, base + UTMIP_XCVR_CFG1);
return utmip_pad_power_off(phy);
}
@@ -637,9 +638,9 @@ static void utmi_phy_preresume(struct tegra_usb_phy *phy)
void __iomem *base = phy->regs;
unsigned long val;
- val = readl(base + UTMIP_TX_CFG0);
+ val = readl_relaxed(base + UTMIP_TX_CFG0);
val |= UTMIP_HS_DISCON_DISABLE;
- writel(val, base + UTMIP_TX_CFG0);
+ writel_relaxed(val, base + UTMIP_TX_CFG0);
}
static void utmi_phy_postresume(struct tegra_usb_phy *phy)
@@ -647,9 +648,9 @@ static void utmi_phy_postresume(struct tegra_usb_phy *phy)
void __iomem *base = phy->regs;
unsigned long val;
- val = readl(base + UTMIP_TX_CFG0);
+ val = readl_relaxed(base + UTMIP_TX_CFG0);
val &= ~UTMIP_HS_DISCON_DISABLE;
- writel(val, base + UTMIP_TX_CFG0);
+ writel_relaxed(val, base + UTMIP_TX_CFG0);
}
static void utmi_phy_restore_start(struct tegra_usb_phy *phy,
@@ -658,18 +659,18 @@ static void utmi_phy_restore_start(struct tegra_usb_phy *phy,
void __iomem *base = phy->regs;
unsigned long val;
- val = readl(base + UTMIP_MISC_CFG0);
+ val = readl_relaxed(base + UTMIP_MISC_CFG0);
val &= ~UTMIP_DPDM_OBSERVE_SEL(~0);
if (port_speed == TEGRA_USB_PHY_PORT_SPEED_LOW)
val |= UTMIP_DPDM_OBSERVE_SEL_FS_K;
else
val |= UTMIP_DPDM_OBSERVE_SEL_FS_J;
- writel(val, base + UTMIP_MISC_CFG0);
+ writel_relaxed(val, base + UTMIP_MISC_CFG0);
usleep_range(1, 10);
- val = readl(base + UTMIP_MISC_CFG0);
+ val = readl_relaxed(base + UTMIP_MISC_CFG0);
val |= UTMIP_DPDM_OBSERVE;
- writel(val, base + UTMIP_MISC_CFG0);
+ writel_relaxed(val, base + UTMIP_MISC_CFG0);
usleep_range(10, 100);
}
@@ -678,9 +679,9 @@ static void utmi_phy_restore_end(struct tegra_usb_phy *phy)
void __iomem *base = phy->regs;
unsigned long val;
- val = readl(base + UTMIP_MISC_CFG0);
+ val = readl_relaxed(base + UTMIP_MISC_CFG0);
val &= ~UTMIP_DPDM_OBSERVE;
- writel(val, base + UTMIP_MISC_CFG0);
+ writel_relaxed(val, base + UTMIP_MISC_CFG0);
usleep_range(10, 100);
}
@@ -712,31 +713,31 @@ static int ulpi_phy_power_on(struct tegra_usb_phy *phy)
usleep_range(1000, 2000);
- val = readl(base + USB_SUSP_CTRL);
+ val = readl_relaxed(base + USB_SUSP_CTRL);
val |= UHSIC_RESET;
- writel(val, base + USB_SUSP_CTRL);
+ writel_relaxed(val, base + USB_SUSP_CTRL);
- val = readl(base + ULPI_TIMING_CTRL_0);
+ val = readl_relaxed(base + ULPI_TIMING_CTRL_0);
val |= ULPI_OUTPUT_PINMUX_BYP | ULPI_CLKOUT_PINMUX_BYP;
- writel(val, base + ULPI_TIMING_CTRL_0);
+ writel_relaxed(val, base + ULPI_TIMING_CTRL_0);
- val = readl(base + USB_SUSP_CTRL);
+ val = readl_relaxed(base + USB_SUSP_CTRL);
val |= ULPI_PHY_ENABLE;
- writel(val, base + USB_SUSP_CTRL);
+ writel_relaxed(val, base + USB_SUSP_CTRL);
val = 0;
- writel(val, base + ULPI_TIMING_CTRL_1);
+ writel_relaxed(val, base + ULPI_TIMING_CTRL_1);
val |= ULPI_DATA_TRIMMER_SEL(4);
val |= ULPI_STPDIRNXT_TRIMMER_SEL(4);
val |= ULPI_DIR_TRIMMER_SEL(4);
- writel(val, base + ULPI_TIMING_CTRL_1);
+ writel_relaxed(val, base + ULPI_TIMING_CTRL_1);
usleep_range(10, 100);
val |= ULPI_DATA_TRIMMER_LOAD;
val |= ULPI_STPDIRNXT_TRIMMER_LOAD;
val |= ULPI_DIR_TRIMMER_LOAD;
- writel(val, base + ULPI_TIMING_CTRL_1);
+ writel_relaxed(val, base + ULPI_TIMING_CTRL_1);
/* Fix VbusInvalid due to floating VBUS */
err = usb_phy_io_write(phy->ulpi, 0x40, 0x08);
@@ -751,14 +752,14 @@ static int ulpi_phy_power_on(struct tegra_usb_phy *phy)
goto disable_clk;
}
- val = readl(base + USB_SUSP_CTRL);
+ val = readl_relaxed(base + USB_SUSP_CTRL);
val |= USB_SUSP_CLR;
- writel(val, base + USB_SUSP_CTRL);
+ writel_relaxed(val, base + USB_SUSP_CTRL);
usleep_range(100, 1000);
- val = readl(base + USB_SUSP_CTRL);
+ val = readl_relaxed(base + USB_SUSP_CTRL);
val &= ~USB_SUSP_CLR;
- writel(val, base + USB_SUSP_CTRL);
+ writel_relaxed(val, base + USB_SUSP_CTRL);
return 0;
--
2.24.0
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCH v4 09/20] usb: phy: tegra: Use generic stub for a missing VBUS regulator
2020-01-06 1:33 [PATCH v4 00/20] NVIDIA Tegra USB2 drivers clean up Dmitry Osipenko
` (7 preceding siblings ...)
2020-01-06 1:34 ` [PATCH v4 08/20] usb: phy: tegra: Use relaxed versions of readl/writel Dmitry Osipenko
@ 2020-01-06 1:34 ` Dmitry Osipenko
2020-01-06 1:34 ` [PATCH v4 10/20] usb: ulpi: Add resource-managed variant of otg_ulpi_create() Dmitry Osipenko
` (10 subsequent siblings)
19 siblings, 0 replies; 23+ messages in thread
From: Dmitry Osipenko @ 2020-01-06 1:34 UTC (permalink / raw)
To: Greg Kroah-Hartman, Peter Chen, Thierry Reding, Jonathan Hunter,
Felipe Balbi, Michał Mirosław
Cc: linux-usb, linux-tegra, linux-kernel
Regulator core provides dummy regulator if device-tree doesn't define VBUS
regulator.
Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
---
drivers/usb/phy/phy-tegra-usb.c | 28 +++++++++-------------------
1 file changed, 9 insertions(+), 19 deletions(-)
diff --git a/drivers/usb/phy/phy-tegra-usb.c b/drivers/usb/phy/phy-tegra-usb.c
index 268b9d9ce57e..5b9f031619c5 100644
--- a/drivers/usb/phy/phy-tegra-usb.c
+++ b/drivers/usb/phy/phy-tegra-usb.c
@@ -836,9 +836,7 @@ static void tegra_usb_phy_shutdown(struct usb_phy *u_phy)
if (!phy->is_ulpi_phy)
utmip_pad_close(phy);
- if (!IS_ERR(phy->vbus))
- regulator_disable(phy->vbus);
-
+ regulator_disable(phy->vbus);
clk_disable_unprepare(phy->pll_u);
phy->freq = NULL;
@@ -900,14 +898,11 @@ static int tegra_usb_phy_init(struct usb_phy *u_phy)
goto fail;
}
- if (!IS_ERR(phy->vbus)) {
- err = regulator_enable(phy->vbus);
- if (err) {
- dev_err(phy->u_phy.dev,
- "Failed to enable USB VBUS regulator: %d\n",
- err);
- goto fail;
- }
+ err = regulator_enable(phy->vbus);
+ if (err) {
+ dev_err(phy->u_phy.dev,
+ "Failed to enable USB VBUS regulator: %d\n", err);
+ goto fail;
}
if (phy->is_ulpi_phy)
@@ -1140,14 +1135,9 @@ static int tegra_usb_phy_probe(struct platform_device *pdev)
}
/* On some boards, the VBUS regulator doesn't need to be controlled */
- if (of_find_property(np, "vbus-supply", NULL)) {
- tegra_phy->vbus = devm_regulator_get(&pdev->dev, "vbus");
- if (IS_ERR(tegra_phy->vbus))
- return PTR_ERR(tegra_phy->vbus);
- } else {
- dev_notice(&pdev->dev, "no vbus regulator");
- tegra_phy->vbus = ERR_PTR(-ENODEV);
- }
+ tegra_phy->vbus = devm_regulator_get(&pdev->dev, "vbus");
+ if (IS_ERR(tegra_phy->vbus))
+ return PTR_ERR(tegra_phy->vbus);
tegra_phy->pll_u = devm_clk_get(&pdev->dev, "pll_u");
err = PTR_ERR_OR_ZERO(tegra_phy->pll_u);
--
2.24.0
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCH v4 10/20] usb: ulpi: Add resource-managed variant of otg_ulpi_create()
2020-01-06 1:33 [PATCH v4 00/20] NVIDIA Tegra USB2 drivers clean up Dmitry Osipenko
` (8 preceding siblings ...)
2020-01-06 1:34 ` [PATCH v4 09/20] usb: phy: tegra: Use generic stub for a missing VBUS regulator Dmitry Osipenko
@ 2020-01-06 1:34 ` Dmitry Osipenko
2020-01-06 1:34 ` [PATCH v4 11/20] usb: phy: tegra: Use devm_otg_ulpi_create() Dmitry Osipenko
` (9 subsequent siblings)
19 siblings, 0 replies; 23+ messages in thread
From: Dmitry Osipenko @ 2020-01-06 1:34 UTC (permalink / raw)
To: Greg Kroah-Hartman, Peter Chen, Thierry Reding, Jonathan Hunter,
Felipe Balbi, Michał Mirosław
Cc: linux-usb, linux-tegra, linux-kernel
Now drivers (like NVIDIA Tegra USB PHY for example) will be able to
benefit from the resource-managed variant, making driver's code a bit
cleaner.
Suggested-by: Thierry Reding <thierry.reding@gmail.com>
Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
---
drivers/usb/phy/phy-ulpi.c | 48 +++++++++++++++++++++++++++++++-------
include/linux/usb/ulpi.h | 11 +++++++++
2 files changed, 50 insertions(+), 9 deletions(-)
diff --git a/drivers/usb/phy/phy-ulpi.c b/drivers/usb/phy/phy-ulpi.c
index a43c49369a60..e683a37e3a7a 100644
--- a/drivers/usb/phy/phy-ulpi.c
+++ b/drivers/usb/phy/phy-ulpi.c
@@ -240,6 +240,21 @@ static int ulpi_set_vbus(struct usb_otg *otg, bool on)
return usb_phy_io_write(phy, flags, ULPI_OTG_CTRL);
}
+static void otg_ulpi_init(struct usb_phy *phy, struct usb_otg *otg,
+ struct usb_phy_io_ops *ops,
+ unsigned int flags)
+{
+ phy->label = "ULPI";
+ phy->flags = flags;
+ phy->io_ops = ops;
+ phy->otg = otg;
+ phy->init = ulpi_init;
+
+ otg->usb_phy = phy;
+ otg->set_host = ulpi_set_host;
+ otg->set_vbus = ulpi_set_vbus;
+}
+
struct usb_phy *
otg_ulpi_create(struct usb_phy_io_ops *ops,
unsigned int flags)
@@ -257,17 +272,32 @@ otg_ulpi_create(struct usb_phy_io_ops *ops,
return NULL;
}
- phy->label = "ULPI";
- phy->flags = flags;
- phy->io_ops = ops;
- phy->otg = otg;
- phy->init = ulpi_init;
-
- otg->usb_phy = phy;
- otg->set_host = ulpi_set_host;
- otg->set_vbus = ulpi_set_vbus;
+ otg_ulpi_init(phy, otg, ops, flags);
return phy;
}
EXPORT_SYMBOL_GPL(otg_ulpi_create);
+struct usb_phy *
+devm_otg_ulpi_create(struct device *dev,
+ struct usb_phy_io_ops *ops,
+ unsigned int flags)
+{
+ struct usb_phy *phy;
+ struct usb_otg *otg;
+
+ phy = devm_kzalloc(dev, sizeof(*phy), GFP_KERNEL);
+ if (!phy)
+ return NULL;
+
+ otg = devm_kzalloc(dev, sizeof(*otg), GFP_KERNEL);
+ if (!otg) {
+ devm_kfree(dev, phy);
+ return NULL;
+ }
+
+ otg_ulpi_init(phy, otg, ops, flags);
+
+ return phy;
+}
+EXPORT_SYMBOL_GPL(devm_otg_ulpi_create);
diff --git a/include/linux/usb/ulpi.h b/include/linux/usb/ulpi.h
index c515765adab7..36c2982780ad 100644
--- a/include/linux/usb/ulpi.h
+++ b/include/linux/usb/ulpi.h
@@ -55,12 +55,23 @@
#if IS_ENABLED(CONFIG_USB_ULPI)
struct usb_phy *otg_ulpi_create(struct usb_phy_io_ops *ops,
unsigned int flags);
+
+struct usb_phy *devm_otg_ulpi_create(struct device *dev,
+ struct usb_phy_io_ops *ops,
+ unsigned int flags);
#else
static inline struct usb_phy *otg_ulpi_create(struct usb_phy_io_ops *ops,
unsigned int flags)
{
return NULL;
}
+
+static inline struct usb_phy *devm_otg_ulpi_create(struct device *dev,
+ struct usb_phy_io_ops *ops,
+ unsigned int flags)
+{
+ return NULL;
+}
#endif
#ifdef CONFIG_USB_ULPI_VIEWPORT
--
2.24.0
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCH v4 11/20] usb: phy: tegra: Use devm_otg_ulpi_create()
2020-01-06 1:33 [PATCH v4 00/20] NVIDIA Tegra USB2 drivers clean up Dmitry Osipenko
` (9 preceding siblings ...)
2020-01-06 1:34 ` [PATCH v4 10/20] usb: ulpi: Add resource-managed variant of otg_ulpi_create() Dmitry Osipenko
@ 2020-01-06 1:34 ` Dmitry Osipenko
2020-01-06 1:34 ` [PATCH v4 12/20] usb: phy: tegra: Use u32 for hardware register variables Dmitry Osipenko
` (8 subsequent siblings)
19 siblings, 0 replies; 23+ messages in thread
From: Dmitry Osipenko @ 2020-01-06 1:34 UTC (permalink / raw)
To: Greg Kroah-Hartman, Peter Chen, Thierry Reding, Jonathan Hunter,
Felipe Balbi, Michał Mirosław
Cc: linux-usb, linux-tegra, linux-kernel
The resource-managed variant removes the necessity for the driver to care
about freeing ULPI resources.
Suggested-by: Thierry Reding <thierry.reding@gmail.com>
Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
---
drivers/usb/phy/phy-tegra-usb.c | 22 ++++++----------------
1 file changed, 6 insertions(+), 16 deletions(-)
diff --git a/drivers/usb/phy/phy-tegra-usb.c b/drivers/usb/phy/phy-tegra-usb.c
index 5b9f031619c5..9adbcdf8d3a1 100644
--- a/drivers/usb/phy/phy-tegra-usb.c
+++ b/drivers/usb/phy/phy-tegra-usb.c
@@ -1100,6 +1100,7 @@ static int tegra_usb_phy_probe(struct platform_device *pdev)
enum usb_phy_interface phy_type;
struct reset_control *reset;
struct resource *res;
+ struct usb_phy *phy;
int err;
tegra_phy = devm_kzalloc(&pdev->dev, sizeof(*tegra_phy), GFP_KERNEL);
@@ -1200,12 +1201,14 @@ static int tegra_usb_phy_probe(struct platform_device *pdev)
return err;
}
- tegra_phy->ulpi = otg_ulpi_create(&ulpi_viewport_access_ops, 0);
- if (!tegra_phy->ulpi) {
+ phy = devm_otg_ulpi_create(&pdev->dev,
+ &ulpi_viewport_access_ops, 0);
+ if (!phy) {
dev_err(&pdev->dev, "Failed to create ULPI OTG\n");
return -ENOMEM;
}
+ tegra_phy->ulpi = phy;
tegra_phy->ulpi->io_priv = tegra_phy->regs + ULPI_VIEWPORT;
break;
@@ -1224,17 +1227,9 @@ static int tegra_usb_phy_probe(struct platform_device *pdev)
err = usb_add_phy_dev(&tegra_phy->u_phy);
if (err)
- goto free_ulpi;
+ return err;
return 0;
-
-free_ulpi:
- if (tegra_phy->ulpi) {
- kfree(tegra_phy->ulpi->otg);
- kfree(tegra_phy->ulpi);
- }
-
- return err;
}
static int tegra_usb_phy_remove(struct platform_device *pdev)
@@ -1243,11 +1238,6 @@ static int tegra_usb_phy_remove(struct platform_device *pdev)
usb_remove_phy(&tegra_phy->u_phy);
- if (tegra_phy->ulpi) {
- kfree(tegra_phy->ulpi->otg);
- kfree(tegra_phy->ulpi);
- }
-
return 0;
}
--
2.24.0
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCH v4 12/20] usb: phy: tegra: Use u32 for hardware register variables
2020-01-06 1:33 [PATCH v4 00/20] NVIDIA Tegra USB2 drivers clean up Dmitry Osipenko
` (10 preceding siblings ...)
2020-01-06 1:34 ` [PATCH v4 11/20] usb: phy: tegra: Use devm_otg_ulpi_create() Dmitry Osipenko
@ 2020-01-06 1:34 ` Dmitry Osipenko
2020-01-06 1:34 ` [PATCH v4 13/20] usb: phy: tegra: Use device-tree notion of reset-GPIO's active-state Dmitry Osipenko
` (7 subsequent siblings)
19 siblings, 0 replies; 23+ messages in thread
From: Dmitry Osipenko @ 2020-01-06 1:34 UTC (permalink / raw)
To: Greg Kroah-Hartman, Peter Chen, Thierry Reding, Jonathan Hunter,
Felipe Balbi, Michał Mirosław
Cc: linux-usb, linux-tegra, linux-kernel
There is a mix of u32/ULONG usage in the driver's code. Let's switch to
u32 uniformly, for consistency.
Suggested-by: Thierry Reding <thierry.reding@gmail.com>
Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
---
drivers/usb/phy/phy-tegra-usb.c | 28 +++++++++++++++-------------
1 file changed, 15 insertions(+), 13 deletions(-)
diff --git a/drivers/usb/phy/phy-tegra-usb.c b/drivers/usb/phy/phy-tegra-usb.c
index 9adbcdf8d3a1..f9acbab477cf 100644
--- a/drivers/usb/phy/phy-tegra-usb.c
+++ b/drivers/usb/phy/phy-tegra-usb.c
@@ -204,7 +204,7 @@ static inline struct tegra_usb_phy *to_tegra_usb_phy(struct usb_phy *u_phy)
static void set_pts(struct tegra_usb_phy *phy, u8 pts_val)
{
void __iomem *base = phy->regs;
- unsigned long val;
+ u32 val;
if (phy->soc_config->has_hostpc) {
val = readl_relaxed(base + TEGRA_USB_HOSTPC1_DEVLC);
@@ -223,7 +223,7 @@ static void set_pts(struct tegra_usb_phy *phy, u8 pts_val)
static void set_phcd(struct tegra_usb_phy *phy, bool enable)
{
void __iomem *base = phy->regs;
- unsigned long val;
+ u32 val;
if (phy->soc_config->has_hostpc) {
val = readl_relaxed(base + TEGRA_USB_HOSTPC1_DEVLC);
@@ -310,7 +310,8 @@ static int utmip_pad_power_on(struct tegra_usb_phy *phy)
{
struct tegra_utmip_config *config = phy->config;
void __iomem *base = phy->pad_regs;
- unsigned long val, flags;
+ unsigned long flags;
+ u32 val;
int err;
err = clk_prepare_enable(phy->pad_clk);
@@ -345,7 +346,8 @@ static int utmip_pad_power_on(struct tegra_usb_phy *phy)
static int utmip_pad_power_off(struct tegra_usb_phy *phy)
{
void __iomem *base = phy->pad_regs;
- unsigned long val, flags;
+ unsigned long flags;
+ u32 val;
int err;
if (!utmip_pad_count) {
@@ -383,7 +385,7 @@ static int utmi_wait_register(void __iomem *reg, u32 mask, u32 result)
static void utmi_phy_clk_disable(struct tegra_usb_phy *phy)
{
void __iomem *base = phy->regs;
- unsigned long val;
+ u32 val;
/*
* The USB driver may have already initiated the phy clock
@@ -415,7 +417,7 @@ static void utmi_phy_clk_disable(struct tegra_usb_phy *phy)
static void utmi_phy_clk_enable(struct tegra_usb_phy *phy)
{
void __iomem *base = phy->regs;
- unsigned long val;
+ u32 val;
/*
* The USB driver may have already initiated the phy clock
@@ -450,7 +452,7 @@ static int utmi_phy_power_on(struct tegra_usb_phy *phy)
{
struct tegra_utmip_config *config = phy->config;
void __iomem *base = phy->regs;
- unsigned long val;
+ u32 val;
int err;
val = readl_relaxed(base + USB_SUSP_CTRL);
@@ -601,7 +603,7 @@ static int utmi_phy_power_on(struct tegra_usb_phy *phy)
static int utmi_phy_power_off(struct tegra_usb_phy *phy)
{
void __iomem *base = phy->regs;
- unsigned long val;
+ u32 val;
utmi_phy_clk_disable(phy);
@@ -636,7 +638,7 @@ static int utmi_phy_power_off(struct tegra_usb_phy *phy)
static void utmi_phy_preresume(struct tegra_usb_phy *phy)
{
void __iomem *base = phy->regs;
- unsigned long val;
+ u32 val;
val = readl_relaxed(base + UTMIP_TX_CFG0);
val |= UTMIP_HS_DISCON_DISABLE;
@@ -646,7 +648,7 @@ static void utmi_phy_preresume(struct tegra_usb_phy *phy)
static void utmi_phy_postresume(struct tegra_usb_phy *phy)
{
void __iomem *base = phy->regs;
- unsigned long val;
+ u32 val;
val = readl_relaxed(base + UTMIP_TX_CFG0);
val &= ~UTMIP_HS_DISCON_DISABLE;
@@ -657,7 +659,7 @@ static void utmi_phy_restore_start(struct tegra_usb_phy *phy,
enum tegra_usb_phy_port_speed port_speed)
{
void __iomem *base = phy->regs;
- unsigned long val;
+ u32 val;
val = readl_relaxed(base + UTMIP_MISC_CFG0);
val &= ~UTMIP_DPDM_OBSERVE_SEL(~0);
@@ -677,7 +679,7 @@ static void utmi_phy_restore_start(struct tegra_usb_phy *phy,
static void utmi_phy_restore_end(struct tegra_usb_phy *phy)
{
void __iomem *base = phy->regs;
- unsigned long val;
+ u32 val;
val = readl_relaxed(base + UTMIP_MISC_CFG0);
val &= ~UTMIP_DPDM_OBSERVE;
@@ -688,7 +690,7 @@ static void utmi_phy_restore_end(struct tegra_usb_phy *phy)
static int ulpi_phy_power_on(struct tegra_usb_phy *phy)
{
void __iomem *base = phy->regs;
- unsigned long val;
+ u32 val;
int err;
err = gpio_direction_output(phy->reset_gpio, 0);
--
2.24.0
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCH v4 13/20] usb: phy: tegra: Use device-tree notion of reset-GPIO's active-state
2020-01-06 1:33 [PATCH v4 00/20] NVIDIA Tegra USB2 drivers clean up Dmitry Osipenko
` (11 preceding siblings ...)
2020-01-06 1:34 ` [PATCH v4 12/20] usb: phy: tegra: Use u32 for hardware register variables Dmitry Osipenko
@ 2020-01-06 1:34 ` Dmitry Osipenko
2020-01-06 1:34 ` [PATCH v4 14/20] usb: phy: tegra: Disable VBUS regulator on tegra_usb_phy_init failure Dmitry Osipenko
` (6 subsequent siblings)
19 siblings, 0 replies; 23+ messages in thread
From: Dmitry Osipenko @ 2020-01-06 1:34 UTC (permalink / raw)
To: Greg Kroah-Hartman, Peter Chen, Thierry Reding, Jonathan Hunter,
Felipe Balbi, Michał Mirosław
Cc: linux-usb, linux-tegra, linux-kernel
It is much more intuitive if reset is treated as asserted when GPIO value
is set to 1. All NVIDIA Tegra device-trees are properly specifying active
state of the reset-GPIO since 2013, let's clean up that part of the code.
Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
---
drivers/usb/phy/phy-tegra-usb.c | 70 +++++++------------------------
include/linux/usb/tegra_usb_phy.h | 3 +-
2 files changed, 18 insertions(+), 55 deletions(-)
diff --git a/drivers/usb/phy/phy-tegra-usb.c b/drivers/usb/phy/phy-tegra-usb.c
index f9acbab477cf..c431968d0433 100644
--- a/drivers/usb/phy/phy-tegra-usb.c
+++ b/drivers/usb/phy/phy-tegra-usb.c
@@ -693,12 +693,7 @@ static int ulpi_phy_power_on(struct tegra_usb_phy *phy)
u32 val;
int err;
- err = gpio_direction_output(phy->reset_gpio, 0);
- if (err) {
- dev_err(phy->u_phy.dev, "GPIO %d not set to 0: %d\n",
- phy->reset_gpio, err);
- return err;
- }
+ gpiod_set_value_cansleep(phy->reset_gpio, 1);
err = clk_prepare_enable(phy->clk);
if (err)
@@ -706,12 +701,7 @@ static int ulpi_phy_power_on(struct tegra_usb_phy *phy)
usleep_range(5000, 6000);
- err = gpio_direction_output(phy->reset_gpio, 1);
- if (err) {
- dev_err(phy->u_phy.dev, "GPIO %d not set to 1: %d\n",
- phy->reset_gpio, err);
- goto disable_clk;
- }
+ gpiod_set_value_cansleep(phy->reset_gpio, 0);
usleep_range(1000, 2000);
@@ -773,16 +763,8 @@ static int ulpi_phy_power_on(struct tegra_usb_phy *phy)
static int ulpi_phy_power_off(struct tegra_usb_phy *phy)
{
- int err;
-
- err = gpio_direction_output(phy->reset_gpio, 0);
- if (err) {
- dev_err(phy->u_phy.dev, "reset GPIO not asserted: %d\n", err);
- return err;
- }
-
+ gpiod_set_value_cansleep(phy->reset_gpio, 1);
usleep_range(5000, 6000);
-
clk_disable_unprepare(phy->clk);
return 0;
@@ -857,21 +839,6 @@ static int tegra_usb_phy_set_suspend(struct usb_phy *u_phy, int suspend)
return tegra_usb_phy_power_on(phy);
}
-static int ulpi_open(struct tegra_usb_phy *phy)
-{
- int err;
-
- err = gpio_direction_output(phy->reset_gpio, 0);
- if (err) {
- dev_err(phy->u_phy.dev,
- "ULPI reset GPIO %d direction not asserted: %d\n",
- phy->reset_gpio, err);
- return err;
- }
-
- return 0;
-}
-
static int tegra_usb_phy_init(struct usb_phy *u_phy)
{
struct tegra_usb_phy *phy = to_tegra_usb_phy(u_phy);
@@ -907,12 +874,11 @@ static int tegra_usb_phy_init(struct usb_phy *u_phy)
goto fail;
}
- if (phy->is_ulpi_phy)
- err = ulpi_open(phy);
- else
+ if (!phy->is_ulpi_phy) {
err = utmip_pad_open(phy);
- if (err)
- goto fail;
+ if (err)
+ goto fail;
+ }
err = tegra_usb_phy_power_on(phy);
if (err)
@@ -1101,6 +1067,7 @@ static int tegra_usb_phy_probe(struct platform_device *pdev)
struct tegra_usb_phy *tegra_phy;
enum usb_phy_interface phy_type;
struct reset_control *reset;
+ struct gpio_desc *gpiod;
struct resource *res;
struct usb_phy *phy;
int err;
@@ -1178,15 +1145,6 @@ static int tegra_usb_phy_probe(struct platform_device *pdev)
case USBPHY_INTERFACE_MODE_ULPI:
tegra_phy->is_ulpi_phy = true;
- tegra_phy->reset_gpio =
- of_get_named_gpio(np, "nvidia,phy-reset-gpio", 0);
-
- if (!gpio_is_valid(tegra_phy->reset_gpio)) {
- dev_err(&pdev->dev,
- "Invalid GPIO: %d\n", tegra_phy->reset_gpio);
- return tegra_phy->reset_gpio;
- }
-
tegra_phy->clk = devm_clk_get(&pdev->dev, "ulpi-link");
err = PTR_ERR_OR_ZERO(tegra_phy->clk);
if (err) {
@@ -1195,13 +1153,17 @@ static int tegra_usb_phy_probe(struct platform_device *pdev)
return err;
}
- err = devm_gpio_request(&pdev->dev, tegra_phy->reset_gpio,
- "ulpi_phy_reset_b");
+ gpiod = devm_gpiod_get_from_of_node(&pdev->dev, np,
+ "nvidia,phy-reset-gpio",
+ 0, GPIOD_OUT_HIGH,
+ "ulpi_phy_reset_b");
+ err = PTR_ERR_OR_ZERO(gpiod);
if (err) {
- dev_err(&pdev->dev, "Request failed for GPIO %d: %d\n",
- tegra_phy->reset_gpio, err);
+ dev_err(&pdev->dev,
+ "Request failed for reset GPIO: %d\n", err);
return err;
}
+ tegra_phy->reset_gpio = gpiod;
phy = devm_otg_ulpi_create(&pdev->dev,
&ulpi_viewport_access_ops, 0);
diff --git a/include/linux/usb/tegra_usb_phy.h b/include/linux/usb/tegra_usb_phy.h
index 3ae73bdc6245..c29d1b4c9381 100644
--- a/include/linux/usb/tegra_usb_phy.h
+++ b/include/linux/usb/tegra_usb_phy.h
@@ -17,6 +17,7 @@
#define __TEGRA_USB_PHY_H
#include <linux/clk.h>
+#include <linux/gpio.h>
#include <linux/reset.h>
#include <linux/usb/otg.h>
@@ -76,7 +77,7 @@ struct tegra_usb_phy {
struct usb_phy u_phy;
bool is_legacy_phy;
bool is_ulpi_phy;
- int reset_gpio;
+ struct gpio_desc *reset_gpio;
struct reset_control *pad_rst;
bool powered_on;
};
--
2.24.0
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCH v4 14/20] usb: phy: tegra: Disable VBUS regulator on tegra_usb_phy_init failure
2020-01-06 1:33 [PATCH v4 00/20] NVIDIA Tegra USB2 drivers clean up Dmitry Osipenko
` (12 preceding siblings ...)
2020-01-06 1:34 ` [PATCH v4 13/20] usb: phy: tegra: Use device-tree notion of reset-GPIO's active-state Dmitry Osipenko
@ 2020-01-06 1:34 ` Dmitry Osipenko
2020-01-06 1:34 ` [PATCH v4 15/20] usb: phy: tegra: Move utmip_pad_count checking under lock Dmitry Osipenko
` (5 subsequent siblings)
19 siblings, 0 replies; 23+ messages in thread
From: Dmitry Osipenko @ 2020-01-06 1:34 UTC (permalink / raw)
To: Greg Kroah-Hartman, Peter Chen, Thierry Reding, Jonathan Hunter,
Felipe Balbi, Michał Mirosław
Cc: linux-usb, linux-tegra, linux-kernel
VBUS regulator should be turned off in a case of error.
Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
---
drivers/usb/phy/phy-tegra-usb.c | 12 ++++++++----
1 file changed, 8 insertions(+), 4 deletions(-)
diff --git a/drivers/usb/phy/phy-tegra-usb.c b/drivers/usb/phy/phy-tegra-usb.c
index c431968d0433..90b42e963a1e 100644
--- a/drivers/usb/phy/phy-tegra-usb.c
+++ b/drivers/usb/phy/phy-tegra-usb.c
@@ -864,20 +864,20 @@ static int tegra_usb_phy_init(struct usb_phy *u_phy)
dev_err(phy->u_phy.dev, "Invalid pll_u parent rate %ld\n",
parent_rate);
err = -EINVAL;
- goto fail;
+ goto disable_clk;
}
err = regulator_enable(phy->vbus);
if (err) {
dev_err(phy->u_phy.dev,
"Failed to enable USB VBUS regulator: %d\n", err);
- goto fail;
+ goto disable_clk;
}
if (!phy->is_ulpi_phy) {
err = utmip_pad_open(phy);
if (err)
- goto fail;
+ goto disable_vbus;
}
err = tegra_usb_phy_power_on(phy);
@@ -889,7 +889,11 @@ static int tegra_usb_phy_init(struct usb_phy *u_phy)
close_phy:
if (!phy->is_ulpi_phy)
utmip_pad_close(phy);
-fail:
+
+disable_vbus:
+ regulator_disable(phy->vbus);
+
+disable_clk:
clk_disable_unprepare(phy->pll_u);
phy->freq = NULL;
--
2.24.0
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCH v4 15/20] usb: phy: tegra: Move utmip_pad_count checking under lock
2020-01-06 1:33 [PATCH v4 00/20] NVIDIA Tegra USB2 drivers clean up Dmitry Osipenko
` (13 preceding siblings ...)
2020-01-06 1:34 ` [PATCH v4 14/20] usb: phy: tegra: Disable VBUS regulator on tegra_usb_phy_init failure Dmitry Osipenko
@ 2020-01-06 1:34 ` Dmitry Osipenko
2020-01-06 1:34 ` [PATCH v4 16/20] usb: phy: tegra: Keep CPU interrupts enabled Dmitry Osipenko
` (4 subsequent siblings)
19 siblings, 0 replies; 23+ messages in thread
From: Dmitry Osipenko @ 2020-01-06 1:34 UTC (permalink / raw)
To: Greg Kroah-Hartman, Peter Chen, Thierry Reding, Jonathan Hunter,
Felipe Balbi, Michał Mirosław
Cc: linux-usb, linux-tegra, linux-kernel
It's unlikely that two drivers could manage PHY's state simultaneously in
practice, nevertheless the utmip_pad_count checking should be under lock,
for consistency.
Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
---
drivers/usb/phy/phy-tegra-usb.c | 21 +++++++++++----------
1 file changed, 11 insertions(+), 10 deletions(-)
diff --git a/drivers/usb/phy/phy-tegra-usb.c b/drivers/usb/phy/phy-tegra-usb.c
index 90b42e963a1e..1b9667b0aa11 100644
--- a/drivers/usb/phy/phy-tegra-usb.c
+++ b/drivers/usb/phy/phy-tegra-usb.c
@@ -348,30 +348,31 @@ static int utmip_pad_power_off(struct tegra_usb_phy *phy)
void __iomem *base = phy->pad_regs;
unsigned long flags;
u32 val;
- int err;
+ int ret;
+
+ ret = clk_prepare_enable(phy->pad_clk);
+ if (ret)
+ return ret;
+
+ spin_lock_irqsave(&utmip_pad_lock, flags);
if (!utmip_pad_count) {
dev_err(phy->u_phy.dev, "UTMIP pad already powered off\n");
- return -EINVAL;
+ ret = -EINVAL;
+ goto ulock;
}
- err = clk_prepare_enable(phy->pad_clk);
- if (err)
- return err;
-
- spin_lock_irqsave(&utmip_pad_lock, flags);
-
if (--utmip_pad_count == 0) {
val = readl_relaxed(base + UTMIP_BIAS_CFG0);
val |= UTMIP_OTGPD | UTMIP_BIASPD;
writel_relaxed(val, base + UTMIP_BIAS_CFG0);
}
-
+ulock:
spin_unlock_irqrestore(&utmip_pad_lock, flags);
clk_disable_unprepare(phy->pad_clk);
- return 0;
+ return ret;
}
static int utmi_wait_register(void __iomem *reg, u32 mask, u32 result)
--
2.24.0
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCH v4 16/20] usb: phy: tegra: Keep CPU interrupts enabled
2020-01-06 1:33 [PATCH v4 00/20] NVIDIA Tegra USB2 drivers clean up Dmitry Osipenko
` (14 preceding siblings ...)
2020-01-06 1:34 ` [PATCH v4 15/20] usb: phy: tegra: Move utmip_pad_count checking under lock Dmitry Osipenko
@ 2020-01-06 1:34 ` Dmitry Osipenko
2020-01-06 1:34 ` [PATCH v4 17/20] usb: chipidea: tegra: Stop managing PHY's power Dmitry Osipenko
` (3 subsequent siblings)
19 siblings, 0 replies; 23+ messages in thread
From: Dmitry Osipenko @ 2020-01-06 1:34 UTC (permalink / raw)
To: Greg Kroah-Hartman, Peter Chen, Thierry Reding, Jonathan Hunter,
Felipe Balbi, Michał Mirosław
Cc: linux-usb, linux-tegra, linux-kernel
There is no good reason for disabling of CPU interrupts in order to
protect the utmip_pad_count modification.
Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
---
drivers/usb/phy/phy-tegra-usb.c | 10 ++++------
1 file changed, 4 insertions(+), 6 deletions(-)
diff --git a/drivers/usb/phy/phy-tegra-usb.c b/drivers/usb/phy/phy-tegra-usb.c
index 1b9667b0aa11..037e8eee737d 100644
--- a/drivers/usb/phy/phy-tegra-usb.c
+++ b/drivers/usb/phy/phy-tegra-usb.c
@@ -310,7 +310,6 @@ static int utmip_pad_power_on(struct tegra_usb_phy *phy)
{
struct tegra_utmip_config *config = phy->config;
void __iomem *base = phy->pad_regs;
- unsigned long flags;
u32 val;
int err;
@@ -318,7 +317,7 @@ static int utmip_pad_power_on(struct tegra_usb_phy *phy)
if (err)
return err;
- spin_lock_irqsave(&utmip_pad_lock, flags);
+ spin_lock(&utmip_pad_lock);
if (utmip_pad_count++ == 0) {
val = readl_relaxed(base + UTMIP_BIAS_CFG0);
@@ -336,7 +335,7 @@ static int utmip_pad_power_on(struct tegra_usb_phy *phy)
writel_relaxed(val, base + UTMIP_BIAS_CFG0);
}
- spin_unlock_irqrestore(&utmip_pad_lock, flags);
+ spin_unlock(&utmip_pad_lock);
clk_disable_unprepare(phy->pad_clk);
@@ -346,7 +345,6 @@ static int utmip_pad_power_on(struct tegra_usb_phy *phy)
static int utmip_pad_power_off(struct tegra_usb_phy *phy)
{
void __iomem *base = phy->pad_regs;
- unsigned long flags;
u32 val;
int ret;
@@ -354,7 +352,7 @@ static int utmip_pad_power_off(struct tegra_usb_phy *phy)
if (ret)
return ret;
- spin_lock_irqsave(&utmip_pad_lock, flags);
+ spin_lock(&utmip_pad_lock);
if (!utmip_pad_count) {
dev_err(phy->u_phy.dev, "UTMIP pad already powered off\n");
@@ -368,7 +366,7 @@ static int utmip_pad_power_off(struct tegra_usb_phy *phy)
writel_relaxed(val, base + UTMIP_BIAS_CFG0);
}
ulock:
- spin_unlock_irqrestore(&utmip_pad_lock, flags);
+ spin_unlock(&utmip_pad_lock);
clk_disable_unprepare(phy->pad_clk);
--
2.24.0
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCH v4 17/20] usb: chipidea: tegra: Stop managing PHY's power
2020-01-06 1:33 [PATCH v4 00/20] NVIDIA Tegra USB2 drivers clean up Dmitry Osipenko
` (15 preceding siblings ...)
2020-01-06 1:34 ` [PATCH v4 16/20] usb: phy: tegra: Keep CPU interrupts enabled Dmitry Osipenko
@ 2020-01-06 1:34 ` Dmitry Osipenko
2020-01-06 1:34 ` [PATCH v4 18/20] usb: chipidea: tegra: Add USB_TEGRA_PHY to driver's dependencies Dmitry Osipenko
` (2 subsequent siblings)
19 siblings, 0 replies; 23+ messages in thread
From: Dmitry Osipenko @ 2020-01-06 1:34 UTC (permalink / raw)
To: Greg Kroah-Hartman, Peter Chen, Thierry Reding, Jonathan Hunter,
Felipe Balbi, Michał Mirosław
Cc: linux-usb, linux-tegra, linux-kernel
Tegra's USB PHY driver now provides generic PHY init/shutdown callbacks
and thus the custom PHY management could be removed from Tegra-specific
part of the ChipIdea driver.
Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
---
drivers/usb/chipidea/ci_hdrc_tegra.c | 9 ---------
1 file changed, 9 deletions(-)
diff --git a/drivers/usb/chipidea/ci_hdrc_tegra.c b/drivers/usb/chipidea/ci_hdrc_tegra.c
index 0c9911d44ee5..7455df0ede49 100644
--- a/drivers/usb/chipidea/ci_hdrc_tegra.c
+++ b/drivers/usb/chipidea/ci_hdrc_tegra.c
@@ -83,13 +83,6 @@ static int tegra_udc_probe(struct platform_device *pdev)
return err;
}
- /*
- * Tegra's USB PHY driver doesn't implement optional phy_init()
- * hook, so we have to power on UDC controller before ChipIdea
- * driver initialization kicks in.
- */
- usb_phy_set_suspend(udc->phy, 0);
-
/* setup and register ChipIdea HDRC device */
udc->data.name = "tegra-udc";
udc->data.flags = soc->flags;
@@ -109,7 +102,6 @@ static int tegra_udc_probe(struct platform_device *pdev)
return 0;
fail_power_off:
- usb_phy_set_suspend(udc->phy, 1);
clk_disable_unprepare(udc->clk);
return err;
}
@@ -119,7 +111,6 @@ static int tegra_udc_remove(struct platform_device *pdev)
struct tegra_udc *udc = platform_get_drvdata(pdev);
ci_hdrc_remove_device(udc->dev);
- usb_phy_set_suspend(udc->phy, 1);
clk_disable_unprepare(udc->clk);
return 0;
--
2.24.0
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCH v4 18/20] usb: chipidea: tegra: Add USB_TEGRA_PHY to driver's dependencies
2020-01-06 1:33 [PATCH v4 00/20] NVIDIA Tegra USB2 drivers clean up Dmitry Osipenko
` (16 preceding siblings ...)
2020-01-06 1:34 ` [PATCH v4 17/20] usb: chipidea: tegra: Stop managing PHY's power Dmitry Osipenko
@ 2020-01-06 1:34 ` Dmitry Osipenko
2020-01-06 1:34 ` [PATCH v4 19/20] usb: host: ehci-tegra: Stop managing PHY's power Dmitry Osipenko
2020-01-06 1:34 ` [PATCH v4 20/20] usb: host: ehci-tegra: Remove unused fields from tegra_ehci_hcd Dmitry Osipenko
19 siblings, 0 replies; 23+ messages in thread
From: Dmitry Osipenko @ 2020-01-06 1:34 UTC (permalink / raw)
To: Greg Kroah-Hartman, Peter Chen, Thierry Reding, Jonathan Hunter,
Felipe Balbi, Michał Mirosław
Cc: linux-usb, linux-tegra, linux-kernel
Add build dependency on USB_TEGRA_PHY since UDC driver isn't usable
without the PHY.
Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
---
drivers/usb/chipidea/Kconfig | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/usb/chipidea/Kconfig b/drivers/usb/chipidea/Kconfig
index ae850b3fddf2..d53db520e209 100644
--- a/drivers/usb/chipidea/Kconfig
+++ b/drivers/usb/chipidea/Kconfig
@@ -7,6 +7,7 @@ config USB_CHIPIDEA
select RESET_CONTROLLER
select USB_ULPI_BUS
select USB_ROLE_SWITCH
+ select USB_TEGRA_PHY if ARCH_TEGRA
help
Say Y here if your system has a dual role high speed USB
controller based on ChipIdea silicon IP. It supports:
--
2.24.0
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCH v4 19/20] usb: host: ehci-tegra: Stop managing PHY's power
2020-01-06 1:33 [PATCH v4 00/20] NVIDIA Tegra USB2 drivers clean up Dmitry Osipenko
` (17 preceding siblings ...)
2020-01-06 1:34 ` [PATCH v4 18/20] usb: chipidea: tegra: Add USB_TEGRA_PHY to driver's dependencies Dmitry Osipenko
@ 2020-01-06 1:34 ` Dmitry Osipenko
2020-01-06 1:34 ` [PATCH v4 20/20] usb: host: ehci-tegra: Remove unused fields from tegra_ehci_hcd Dmitry Osipenko
19 siblings, 0 replies; 23+ messages in thread
From: Dmitry Osipenko @ 2020-01-06 1:34 UTC (permalink / raw)
To: Greg Kroah-Hartman, Peter Chen, Thierry Reding, Jonathan Hunter,
Felipe Balbi, Michał Mirosław
Cc: linux-usb, linux-tegra, linux-kernel
There is no need to use usb_phy_set_suspend during of driver's probe
because now PHY driver enables hardware during of PHY's initialization.
Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
---
drivers/usb/host/ehci-tegra.c | 6 ------
1 file changed, 6 deletions(-)
diff --git a/drivers/usb/host/ehci-tegra.c b/drivers/usb/host/ehci-tegra.c
index 32483bef046b..1eb94205a5ac 100644
--- a/drivers/usb/host/ehci-tegra.c
+++ b/drivers/usb/host/ehci-tegra.c
@@ -480,12 +480,6 @@ static int tegra_ehci_probe(struct platform_device *pdev)
}
u_phy->otg->host = hcd_to_bus(hcd);
- err = usb_phy_set_suspend(hcd->usb_phy, 0);
- if (err) {
- dev_err(&pdev->dev, "Failed to power on the phy\n");
- goto cleanup_phy;
- }
-
irq = platform_get_irq(pdev, 0);
if (!irq) {
dev_err(&pdev->dev, "Failed to get IRQ\n");
--
2.24.0
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCH v4 20/20] usb: host: ehci-tegra: Remove unused fields from tegra_ehci_hcd
2020-01-06 1:33 [PATCH v4 00/20] NVIDIA Tegra USB2 drivers clean up Dmitry Osipenko
` (18 preceding siblings ...)
2020-01-06 1:34 ` [PATCH v4 19/20] usb: host: ehci-tegra: Stop managing PHY's power Dmitry Osipenko
@ 2020-01-06 1:34 ` Dmitry Osipenko
2020-01-06 15:16 ` Alan Stern
19 siblings, 1 reply; 23+ messages in thread
From: Dmitry Osipenko @ 2020-01-06 1:34 UTC (permalink / raw)
To: Greg Kroah-Hartman, Peter Chen, Thierry Reding, Jonathan Hunter,
Felipe Balbi, Michał Mirosław
Cc: linux-usb, linux-tegra, linux-kernel
There are few stale fields in tegra_ehci_hcd structure, let's remove them.
Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
---
drivers/usb/host/ehci-tegra.c | 2 --
1 file changed, 2 deletions(-)
diff --git a/drivers/usb/host/ehci-tegra.c b/drivers/usb/host/ehci-tegra.c
index 1eb94205a5ac..d6433f206c17 100644
--- a/drivers/usb/host/ehci-tegra.c
+++ b/drivers/usb/host/ehci-tegra.c
@@ -42,12 +42,10 @@ struct tegra_ehci_soc_config {
};
struct tegra_ehci_hcd {
- struct tegra_usb_phy *phy;
struct clk *clk;
struct reset_control *rst;
int port_resuming;
bool needs_double_reset;
- enum tegra_usb_phy_port_speed port_speed;
};
static int tegra_reset_usb_controller(struct platform_device *pdev)
--
2.24.0
^ permalink raw reply related [flat|nested] 23+ messages in thread
* Re: [PATCH v4 20/20] usb: host: ehci-tegra: Remove unused fields from tegra_ehci_hcd
2020-01-06 1:34 ` [PATCH v4 20/20] usb: host: ehci-tegra: Remove unused fields from tegra_ehci_hcd Dmitry Osipenko
@ 2020-01-06 15:16 ` Alan Stern
2020-01-07 16:13 ` Dmitry Osipenko
0 siblings, 1 reply; 23+ messages in thread
From: Alan Stern @ 2020-01-06 15:16 UTC (permalink / raw)
To: Dmitry Osipenko
Cc: Greg Kroah-Hartman, Peter Chen, Thierry Reding, Jonathan Hunter,
Felipe Balbi, Michał Mirosław, linux-usb, linux-tegra,
linux-kernel
On Mon, 6 Jan 2020, Dmitry Osipenko wrote:
> There are few stale fields in tegra_ehci_hcd structure, let's remove them.
>
> Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
> ---
> drivers/usb/host/ehci-tegra.c | 2 --
> 1 file changed, 2 deletions(-)
>
> diff --git a/drivers/usb/host/ehci-tegra.c b/drivers/usb/host/ehci-tegra.c
> index 1eb94205a5ac..d6433f206c17 100644
> --- a/drivers/usb/host/ehci-tegra.c
> +++ b/drivers/usb/host/ehci-tegra.c
> @@ -42,12 +42,10 @@ struct tegra_ehci_soc_config {
> };
>
> struct tegra_ehci_hcd {
> - struct tegra_usb_phy *phy;
> struct clk *clk;
> struct reset_control *rst;
> int port_resuming;
> bool needs_double_reset;
> - enum tegra_usb_phy_port_speed port_speed;
> };
>
> static int tegra_reset_usb_controller(struct platform_device *pdev)
For patches 2, 19, and 20:
Acked-by: Alan Stern <stern@rowland.harvard.edu>
It's nice to see that patch 2 makes the sequence of events in
tegra_ehci_remove() exactly the same as the failure pathway in
tegra_ehci_probe().
Alan Stern
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH v4 20/20] usb: host: ehci-tegra: Remove unused fields from tegra_ehci_hcd
2020-01-06 15:16 ` Alan Stern
@ 2020-01-07 16:13 ` Dmitry Osipenko
0 siblings, 0 replies; 23+ messages in thread
From: Dmitry Osipenko @ 2020-01-07 16:13 UTC (permalink / raw)
To: Alan Stern
Cc: Greg Kroah-Hartman, Peter Chen, Thierry Reding, Jonathan Hunter,
Felipe Balbi, Michał Mirosław, linux-usb, linux-tegra,
linux-kernel
06.01.2020 18:16, Alan Stern пишет:
> On Mon, 6 Jan 2020, Dmitry Osipenko wrote:
>
>> There are few stale fields in tegra_ehci_hcd structure, let's remove them.
>>
>> Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
>> ---
>> drivers/usb/host/ehci-tegra.c | 2 --
>> 1 file changed, 2 deletions(-)
>>
>> diff --git a/drivers/usb/host/ehci-tegra.c b/drivers/usb/host/ehci-tegra.c
>> index 1eb94205a5ac..d6433f206c17 100644
>> --- a/drivers/usb/host/ehci-tegra.c
>> +++ b/drivers/usb/host/ehci-tegra.c
>> @@ -42,12 +42,10 @@ struct tegra_ehci_soc_config {
>> };
>>
>> struct tegra_ehci_hcd {
>> - struct tegra_usb_phy *phy;
>> struct clk *clk;
>> struct reset_control *rst;
>> int port_resuming;
>> bool needs_double_reset;
>> - enum tegra_usb_phy_port_speed port_speed;
>> };
>>
>> static int tegra_reset_usb_controller(struct platform_device *pdev)
>
> For patches 2, 19, and 20:
>
> Acked-by: Alan Stern <stern@rowland.harvard.edu>
>
> It's nice to see that patch 2 makes the sequence of events in
> tegra_ehci_remove() exactly the same as the failure pathway in
> tegra_ehci_probe().
Thank you very much for taking a look at the patches!
^ permalink raw reply [flat|nested] 23+ messages in thread
end of thread, other threads:[~2020-01-07 16:13 UTC | newest]
Thread overview: 23+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-01-06 1:33 [PATCH v4 00/20] NVIDIA Tegra USB2 drivers clean up Dmitry Osipenko
2020-01-06 1:33 ` [PATCH v4 01/20] dt-binding: usb: ci-hdrc-usb2: Document NVIDIA Tegra support Dmitry Osipenko
2020-01-06 1:33 ` [PATCH v4 02/20] usb: host: ehci-tegra: Correct teardown order of driver's removal Dmitry Osipenko
2020-01-06 1:33 ` [PATCH v4 03/20] usb: phy: tegra: Clean up ulpi_phy_power_off Dmitry Osipenko
2020-01-06 1:34 ` [PATCH v4 04/20] usb: phy: tegra: Keep track of power on-off state Dmitry Osipenko
2020-01-06 1:34 ` [PATCH v4 05/20] usb: phy: tegra: Hook up init/shutdown callbacks Dmitry Osipenko
2020-01-06 1:34 ` [PATCH v4 06/20] usb: phy: tegra: Perform general clean up of the code Dmitry Osipenko
2020-01-06 1:34 ` [PATCH v4 07/20] usb: phy: tegra: Clean up included headers Dmitry Osipenko
2020-01-06 1:34 ` [PATCH v4 08/20] usb: phy: tegra: Use relaxed versions of readl/writel Dmitry Osipenko
2020-01-06 1:34 ` [PATCH v4 09/20] usb: phy: tegra: Use generic stub for a missing VBUS regulator Dmitry Osipenko
2020-01-06 1:34 ` [PATCH v4 10/20] usb: ulpi: Add resource-managed variant of otg_ulpi_create() Dmitry Osipenko
2020-01-06 1:34 ` [PATCH v4 11/20] usb: phy: tegra: Use devm_otg_ulpi_create() Dmitry Osipenko
2020-01-06 1:34 ` [PATCH v4 12/20] usb: phy: tegra: Use u32 for hardware register variables Dmitry Osipenko
2020-01-06 1:34 ` [PATCH v4 13/20] usb: phy: tegra: Use device-tree notion of reset-GPIO's active-state Dmitry Osipenko
2020-01-06 1:34 ` [PATCH v4 14/20] usb: phy: tegra: Disable VBUS regulator on tegra_usb_phy_init failure Dmitry Osipenko
2020-01-06 1:34 ` [PATCH v4 15/20] usb: phy: tegra: Move utmip_pad_count checking under lock Dmitry Osipenko
2020-01-06 1:34 ` [PATCH v4 16/20] usb: phy: tegra: Keep CPU interrupts enabled Dmitry Osipenko
2020-01-06 1:34 ` [PATCH v4 17/20] usb: chipidea: tegra: Stop managing PHY's power Dmitry Osipenko
2020-01-06 1:34 ` [PATCH v4 18/20] usb: chipidea: tegra: Add USB_TEGRA_PHY to driver's dependencies Dmitry Osipenko
2020-01-06 1:34 ` [PATCH v4 19/20] usb: host: ehci-tegra: Stop managing PHY's power Dmitry Osipenko
2020-01-06 1:34 ` [PATCH v4 20/20] usb: host: ehci-tegra: Remove unused fields from tegra_ehci_hcd Dmitry Osipenko
2020-01-06 15:16 ` Alan Stern
2020-01-07 16:13 ` Dmitry Osipenko
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).