2013-05-10 14:02:43

by Venu Byravarasu

[permalink] [raw]
Subject: [PATCH v3 00/10] Tegra USB PHY driver series

delta from v2:
This patch is prepared as follow up patch of TEGRA USB PHY driver
patch series discussed at:
http://marc.info/?l=linux-tegra&m=136497946026787&w=2

Venu Byravarasu (10):
ARM: tegra: finalize USB EHCI and PHY bindings
arm: dt: Tegra20: Modify ULPI reset GPIO properties
ARM: tegra: update device trees for USB binding rework
Revert "usb: phy: tegra: don't call into tegra-ehci directly"
usb: phy: tegra: Get PHY mode using DT
usb: phy: tegra: Return correct error value provided by clk_get_sys
usb: phy: tegra: get ULPI reset GPIO info using DT.
usb: phy: tegra: Add error handling & clean up.
usb: phy: registering Tegra USB PHY as platform driver
Usb: Move PORTSC access to PHY

.../bindings/usb/nvidia,tegra20-ehci.txt | 27 +--
.../bindings/usb/nvidia,tegra20-usb-phy.txt | 40 ++-
arch/arm/boot/dts/tegra20-colibri-512.dtsi | 6 +-
arch/arm/boot/dts/tegra20-harmony.dts | 10 +-
arch/arm/boot/dts/tegra20-iris-512.dts | 1 -
arch/arm/boot/dts/tegra20-paz00.dts | 10 +-
arch/arm/boot/dts/tegra20-seaboard.dts | 24 +-
arch/arm/boot/dts/tegra20-trimslice.dts | 23 +-
arch/arm/boot/dts/tegra20-ventana.dts | 10 +-
arch/arm/boot/dts/tegra20-whistler.dts | 26 ++
arch/arm/boot/dts/tegra20.dtsi | 46 ++-
drivers/usb/host/ehci-tegra.c | 143 +++------
drivers/usb/phy/phy-tegra-usb.c | 349 +++++++++++++-------
include/linux/usb/tegra_usb_phy.h | 9 +-
14 files changed, 424 insertions(+), 300 deletions(-)


2013-05-10 14:02:54

by Venu Byravarasu

[permalink] [raw]
Subject: [PATCH v3 01/10] ARM: tegra: finalize USB EHCI and PHY bindings

The existing Tegra USB bindings have a few issues:

1) Many properties are documented as being part of the EHCI controller
node, yet they apply more to the PHY device. They should be moved.

2) Some registers in PHY1 are shared with PHY3, and hence PHY3 needs a
reg entry to point at PHY1's register space. We can't assume the PHY1
driver is present, so the PHY3 driver will directly access those
registers.

3) The list of clocks required by the PHY was missing some required
entries.

4) UTMI PHY Timing parameters are added

5) VBUS control is now specified using a regulator rather than a plain GPIO

6) Added nvidia,is-wired property to indicate whether the device is
hard wired on the board, or pluggable.

This patch fixes the binding definition to resolve these issues.

Signed-off-by: Venu Byravarasu <[email protected]>
---
delta from v1:
1. added UTMI PHY timing params.
2. replaced gadget with peripheral in dr_mode
3. added nvidia,is-wired & vbus-supply params.

delta from v2:
Moved vbus-supply under "Required properties for dr_mode == otg" heading.


.../bindings/usb/nvidia,tegra20-ehci.txt | 27 ++-----------
.../bindings/usb/nvidia,tegra20-usb-phy.txt | 40 ++++++++++++++++++-
2 files changed, 42 insertions(+), 25 deletions(-)

diff --git a/Documentation/devicetree/bindings/usb/nvidia,tegra20-ehci.txt b/Documentation/devicetree/bindings/usb/nvidia,tegra20-ehci.txt
index 34c9528..df09330 100644
--- a/Documentation/devicetree/bindings/usb/nvidia,tegra20-ehci.txt
+++ b/Documentation/devicetree/bindings/usb/nvidia,tegra20-ehci.txt
@@ -6,27 +6,10 @@ Practice : Universal Serial Bus" with the following modifications
and additions :

Required properties :
- - compatible : Should be "nvidia,tegra20-ehci" for USB controllers
- used in host mode.
- - phy_type : Should be one of "ulpi" or "utmi".
- - nvidia,vbus-gpio : If present, specifies a gpio that needs to be
- activated for the bus to be powered.
- - nvidia,phy : phandle of the PHY instance, the controller is connected to.
-
-Required properties for phy_type == ulpi:
- - nvidia,phy-reset-gpio : The GPIO used to reset the PHY.
+ - compatible : Should be "nvidia,tegra20-ehci".
+ - nvidia,phy : phandle of the PHY that the controller is connected to.
+ - clocks : Contains a single entry which defines the USB controller's clock.

Optional properties:
- - dr_mode : dual role mode. Indicates the working mode for
- nvidia,tegra20-ehci compatible controllers. Can be "host", "peripheral",
- or "otg". Default to "host" if not defined for backward compatibility.
- host means this is a host controller
- peripheral means it is device controller
- otg means it can operate as either ("on the go")
- - nvidia,has-legacy-mode : boolean indicates whether this controller can
- operate in legacy mode (as APX 2500 / 2600). In legacy mode some
- registers are accessed through the APB_MISC base address instead of
- the USB controller. Since this is a legacy issue it probably does not
- warrant a compatible string of its own.
- - nvidia,needs-double-reset : boolean is to be set for some of the Tegra2
- USB ports, which need reset twice due to hardware issues.
+ - nvidia,needs-double-reset : boolean is to be set for some of the Tegra20
+ USB ports, which need reset twice due to hardware issues.
diff --git a/Documentation/devicetree/bindings/usb/nvidia,tegra20-usb-phy.txt b/Documentation/devicetree/bindings/usb/nvidia,tegra20-usb-phy.txt
index 6bdaba2..292d8e2 100644
--- a/Documentation/devicetree/bindings/usb/nvidia,tegra20-usb-phy.txt
+++ b/Documentation/devicetree/bindings/usb/nvidia,tegra20-usb-phy.txt
@@ -4,14 +4,48 @@ The device node for Tegra SOC USB PHY:

Required properties :
- compatible : Should be "nvidia,tegra20-usb-phy".
- - reg : Address and length of the register set for the USB PHY interface.
- - phy_type : Should be one of "ulpi" or "utmi".
+ - reg : Defines the following set of registers, in the order listed:
+ - The PHY's own register set.
+ Always present.
+ - The register set of the PHY containing the UTMI pad control registers.
+ Present if-and-only-if phy_type == utmi.
+ - phy_type : Should be one of "utmi", "ulpi" or "hsic".
+ - clocks : Defines the clocks listed in the clock-names property.
+ - clock-names : The following clock names must be present:
+ - reg: The clock needed to access the PHY's own registers. This is the
+ associated EHCI controller's clock. Always present.
+ - pll_u: PLL_U. Always present.
+ - timer: The timeout clock (clk_m). Present if phy_type == utmi.
+ - utmi-pads: The clock needed to access the UTMI pad control registers.
+ Present if phy_type == utmi.
+ - ulpi-link: The clock Tegra provides to the ULPI PHY (cdev2).
+ Present if phy_type == ulpi, and ULPI link mode is in use.

Required properties for phy_type == ulpi:
- nvidia,phy-reset-gpio : The GPIO used to reset the PHY.

+Required PHY timing params for utmi phy:
+ - nvidia,hssync-start-delay : Number of 480 Mhz clock cycles to wait before
+ start of sync launches RxActive
+ - nvidia,elastic-limit : Variable FIFO Depth of elastic input store
+ - nvidia,idle-wait-delay : Number of 480 Mhz clock cycles of idle to wait
+ before declare IDLE.
+ - nvidia,term-range-adj : Range adjusment on terminations
+ - nvidia,xcvr-setup : HS driver output control
+ - nvidia,xcvr-lsfslew : LS falling slew rate control.
+ - nvidia,xcvr-lsrslew : LS rising slew rate control.
+
Optional properties:
- nvidia,has-legacy-mode : boolean indicates whether this controller can
operate in legacy mode (as APX 2500 / 2600). In legacy mode some
registers are accessed through the APB_MISC base address instead of
- the USB controller.
\ No newline at end of file
+ the USB controller.
+ - nvidia,is-wired : boolean. Indicates whether we can do certain kind of power
+ optimizations for the devices that are always connected. e.g. modem.
+ - dr_mode : dual role mode. Indicates the working mode for the PHY. Can be
+ "host", "peripheral", or "otg". Defaults to "host" if not defined.
+ host means this is a host controller
+ peripheral means it is device controller
+ otg means it can operate as either ("on the go")
+Required properties for dr_mode == otg:
+ - vbus-supply: regulator for VBUS
\ No newline at end of file
--
1.7.0.4

2013-05-10 14:03:18

by Venu Byravarasu

[permalink] [raw]
Subject: [PATCH v3 04/10] Revert "usb: phy: tegra: don't call into tegra-ehci directly"

This reverts commit ee5d5499edb94cd03738a52a7e234b139da8fd72.

Signed-off-by: Venu Byravarasu <[email protected]>
---
As PHY is being registered as separate driver, solution proposed with
this patch cannot work anymore.
Hence pushed patch 10 of this series to address the issue.

drivers/usb/host/ehci-tegra.c | 10 +++++-----
drivers/usb/phy/phy-tegra-usb.c | 13 ++++---------
include/linux/usb/tegra_usb_phy.h | 10 +++++-----
3 files changed, 14 insertions(+), 19 deletions(-)

diff --git a/drivers/usb/host/ehci-tegra.c b/drivers/usb/host/ehci-tegra.c
index e3eddc3..ed201ae 100644
--- a/drivers/usb/host/ehci-tegra.c
+++ b/drivers/usb/host/ehci-tegra.c
@@ -611,7 +611,7 @@ static const struct dev_pm_ops tegra_ehci_pm_ops = {
/* Bits of PORTSC1, which will get cleared by writing 1 into them */
#define TEGRA_PORTSC1_RWC_BITS (PORT_CSC | PORT_PEC | PORT_OCC)

-static void tegra_ehci_set_pts(struct usb_phy *x, u8 pts_val)
+void tegra_ehci_set_pts(struct usb_phy *x, u8 pts_val)
{
unsigned long val;
struct usb_hcd *hcd = bus_to_hcd(x->otg->host);
@@ -622,8 +622,9 @@ static void tegra_ehci_set_pts(struct usb_phy *x, u8 pts_val)
val |= TEGRA_USB_PORTSC1_PTS(pts_val & 3);
writel(val, base + TEGRA_USB_PORTSC1);
}
+EXPORT_SYMBOL_GPL(tegra_ehci_set_pts);

-static void tegra_ehci_set_phcd(struct usb_phy *x, bool enable)
+void tegra_ehci_set_phcd(struct usb_phy *x, bool enable)
{
unsigned long val;
struct usb_hcd *hcd = bus_to_hcd(x->otg->host);
@@ -636,6 +637,7 @@ static void tegra_ehci_set_phcd(struct usb_phy *x, bool enable)
val &= ~TEGRA_USB_PORTSC1_PHCD;
writel(val, base + TEGRA_USB_PORTSC1);
}
+EXPORT_SYMBOL_GPL(tegra_ehci_set_phcd);

static u64 tegra_ehci_dma_mask = DMA_BIT_MASK(32);

@@ -736,9 +738,7 @@ static int tegra_ehci_probe(struct platform_device *pdev)

tegra->phy = tegra_usb_phy_open(&pdev->dev, instance, hcd->regs,
pdata->phy_config,
- TEGRA_USB_PHY_MODE_HOST,
- tegra_ehci_set_pts,
- tegra_ehci_set_phcd);
+ TEGRA_USB_PHY_MODE_HOST);
if (IS_ERR(tegra->phy)) {
dev_err(&pdev->dev, "Failed to open USB phy\n");
err = -ENXIO;
diff --git a/drivers/usb/phy/phy-tegra-usb.c b/drivers/usb/phy/phy-tegra-usb.c
index 17d8112..5487d38 100644
--- a/drivers/usb/phy/phy-tegra-usb.c
+++ b/drivers/usb/phy/phy-tegra-usb.c
@@ -299,7 +299,7 @@ static void utmi_phy_clk_disable(struct tegra_usb_phy *phy)
val &= ~USB_SUSP_SET;
writel(val, base + USB_SUSP_CTRL);
} else
- phy->set_phcd(&phy->u_phy, true);
+ tegra_ehci_set_phcd(&phy->u_phy, true);

if (utmi_wait_register(base + USB_SUSP_CTRL, USB_PHY_CLK_VALID, 0) < 0)
pr_err("%s: timeout waiting for phy to stabilize\n", __func__);
@@ -321,7 +321,7 @@ static void utmi_phy_clk_enable(struct tegra_usb_phy *phy)
val &= ~USB_SUSP_CLR;
writel(val, base + USB_SUSP_CTRL);
} else
- phy->set_phcd(&phy->u_phy, false);
+ tegra_ehci_set_phcd(&phy->u_phy, false);

if (utmi_wait_register(base + USB_SUSP_CTRL, USB_PHY_CLK_VALID,
USB_PHY_CLK_VALID))
@@ -444,7 +444,7 @@ static int utmi_phy_power_on(struct tegra_usb_phy *phy)
utmi_phy_clk_enable(phy);

if (!phy->is_legacy_phy)
- phy->set_pts(&phy->u_phy, 0);
+ tegra_ehci_set_pts(&phy->u_phy, 0);

return 0;
}
@@ -688,10 +688,7 @@ static int tegra_usb_phy_suspend(struct usb_phy *x, int suspend)
}

struct tegra_usb_phy *tegra_usb_phy_open(struct device *dev, int instance,
- void __iomem *regs, void *config, enum tegra_usb_phy_mode phy_mode,
- void (*set_pts)(struct usb_phy *x, u8 pts_val),
- void (*set_phcd)(struct usb_phy *x, bool enable))
-
+ void __iomem *regs, void *config, enum tegra_usb_phy_mode phy_mode)
{
struct tegra_usb_phy *phy;
unsigned long parent_rate;
@@ -710,8 +707,6 @@ struct tegra_usb_phy *tegra_usb_phy_open(struct device *dev, int instance,
phy->dev = dev;
phy->is_legacy_phy =
of_property_read_bool(np, "nvidia,has-legacy-mode");
- phy->set_pts = set_pts;
- phy->set_phcd = set_phcd;
err = of_property_match_string(np, "phy_type", "ulpi");
if (err < 0)
phy->is_ulpi_phy = false;
diff --git a/include/linux/usb/tegra_usb_phy.h b/include/linux/usb/tegra_usb_phy.h
index 1b7519a..9ebebe9 100644
--- a/include/linux/usb/tegra_usb_phy.h
+++ b/include/linux/usb/tegra_usb_phy.h
@@ -61,14 +61,10 @@ struct tegra_usb_phy {
struct device *dev;
bool is_legacy_phy;
bool is_ulpi_phy;
- void (*set_pts)(struct usb_phy *x, u8 pts_val);
- void (*set_phcd)(struct usb_phy *x, bool enable);
};

struct tegra_usb_phy *tegra_usb_phy_open(struct device *dev, int instance,
- void __iomem *regs, void *config, enum tegra_usb_phy_mode phy_mode,
- void (*set_pts)(struct usb_phy *x, u8 pts_val),
- void (*set_phcd)(struct usb_phy *x, bool enable));
+ void __iomem *regs, void *config, enum tegra_usb_phy_mode phy_mode);

void tegra_usb_phy_preresume(struct usb_phy *phy);

@@ -79,4 +75,8 @@ void tegra_ehci_phy_restore_start(struct usb_phy *phy,

void tegra_ehci_phy_restore_end(struct usb_phy *phy);

+void tegra_ehci_set_pts(struct usb_phy *x, u8 pts_val);
+
+void tegra_ehci_set_phcd(struct usb_phy *x, bool enable);
+
#endif /* __TEGRA_USB_PHY_H */
--
1.7.0.4

2013-05-10 14:03:23

by Venu Byravarasu

[permalink] [raw]
Subject: [PATCH v3 06/10] usb: phy: tegra: Return correct error value provided by clk_get_sys

In case if clk_get_sys fails, return correct error value provided by
the API.

Signed-off-by: Venu Byravarasu <[email protected]>
---
delta from v1 & v2: no change.

drivers/usb/phy/phy-tegra-usb.c | 3 +--
1 files changed, 1 insertions(+), 2 deletions(-)

diff --git a/drivers/usb/phy/phy-tegra-usb.c b/drivers/usb/phy/phy-tegra-usb.c
index 91b6e29..16851e2 100644
--- a/drivers/usb/phy/phy-tegra-usb.c
+++ b/drivers/usb/phy/phy-tegra-usb.c
@@ -620,8 +620,7 @@ static int tegra_phy_init(struct usb_phy *x)
phy->clk = clk_get_sys(NULL, ulpi_config->clk);
if (IS_ERR(phy->clk)) {
pr_err("%s: can't get ulpi clock\n", __func__);
- err = -ENXIO;
- goto err1;
+ return PTR_ERR(phy->clk);
}
if (!gpio_is_valid(ulpi_config->reset_gpio))
ulpi_config->reset_gpio =
--
1.7.0.4

2013-05-10 14:03:38

by Venu Byravarasu

[permalink] [raw]
Subject: [PATCH v3 09/10] usb: phy: registering Tegra USB PHY as platform driver

Registered Tegra USB PHY as a separate platform driver.

To synchronize host controller and PHY initialization, used deferred
probe mechanism. As PHY should be initialized before EHCI starts running,
deferred probe of Tegra EHCI driver till PHY probe gets completed.

Got rid of instance number based handling in host driver.

Made use of DT params to get the PHY Pad registers.

Signed-off-by: Venu Byravarasu <[email protected]>
---
delta from v1:
1. Removed extra memory allocation for u_phy->otg
2. Moved ulpi_init code into separate function.
3. Initializing all clk and GPIOs in probe.
4. Used devm_ APIs wherever possible.

delta from v2:
Rebased to TOT and applied same changes as on v2.

drivers/usb/host/ehci-tegra.c | 95 +++++-------
drivers/usb/phy/phy-tegra-usb.c | 314 +++++++++++++++++++++----------------
include/linux/usb/tegra_usb_phy.h | 3 +-
3 files changed, 218 insertions(+), 194 deletions(-)

diff --git a/drivers/usb/host/ehci-tegra.c b/drivers/usb/host/ehci-tegra.c
index f4b2164..406abd9 100644
--- a/drivers/usb/host/ehci-tegra.c
+++ b/drivers/usb/host/ehci-tegra.c
@@ -649,7 +649,7 @@ static int tegra_ehci_probe(struct platform_device *pdev)
struct tegra_ehci_platform_data *pdata;
int err = 0;
int irq;
- int instance = pdev->id;
+ struct device_node *np_phy;
struct usb_phy *u_phy;

pdata = pdev->dev.platform_data;
@@ -672,38 +672,49 @@ static int tegra_ehci_probe(struct platform_device *pdev)
if (!tegra)
return -ENOMEM;

- hcd = usb_create_hcd(&tegra_ehci_hc_driver, &pdev->dev,
- dev_name(&pdev->dev));
- if (!hcd) {
- dev_err(&pdev->dev, "Unable to create HCD\n");
- return -ENOMEM;
- }
-
- platform_set_drvdata(pdev, tegra);
-
tegra->clk = devm_clk_get(&pdev->dev, NULL);
if (IS_ERR(tegra->clk)) {
dev_err(&pdev->dev, "Can't get ehci clock\n");
- err = PTR_ERR(tegra->clk);
- goto fail_clk;
+ return PTR_ERR(tegra->clk);
}

err = clk_prepare_enable(tegra->clk);
if (err)
- goto fail_clk;
+ return err;

tegra_periph_reset_assert(tegra->clk);
udelay(1);
tegra_periph_reset_deassert(tegra->clk);

+ np_phy = of_parse_phandle(pdev->dev.of_node, "nvidia,phy", 0);
+ if (!np_phy) {
+ err = -ENODEV;
+ goto cleanup_clk;
+ }
+
+ u_phy = tegra_usb_get_phy(np_phy);
+ if (IS_ERR(u_phy)) {
+ err = PTR_ERR(u_phy);
+ goto cleanup_clk;
+ }
+
tegra->needs_double_reset = of_property_read_bool(pdev->dev.of_node,
"nvidia,needs-double-reset");

+ hcd = usb_create_hcd(&tegra_ehci_hc_driver, &pdev->dev,
+ dev_name(&pdev->dev));
+ if (!hcd) {
+ dev_err(&pdev->dev, "Unable to create HCD\n");
+ err = -ENOMEM;
+ goto cleanup_clk;
+ }
+ hcd->phy = u_phy;
+
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res) {
dev_err(&pdev->dev, "Failed to get I/O memory\n");
err = -ENXIO;
- goto fail_io;
+ goto cleanup_hcd_create;
}
hcd->rsrc_start = res->start;
hcd->rsrc_len = resource_size(res);
@@ -711,55 +722,28 @@ static int tegra_ehci_probe(struct platform_device *pdev)
if (!hcd->regs) {
dev_err(&pdev->dev, "Failed to remap I/O memory\n");
err = -ENOMEM;
- goto fail_io;
- }
-
- /* This is pretty ugly and needs to be fixed when we do only
- * device-tree probing. Old code relies on the platform_device
- * numbering that we lack for device-tree-instantiated devices.
- */
- if (instance < 0) {
- switch (res->start) {
- case TEGRA_USB_BASE:
- instance = 0;
- break;
- case TEGRA_USB2_BASE:
- instance = 1;
- break;
- case TEGRA_USB3_BASE:
- instance = 2;
- break;
- default:
- err = -ENODEV;
- dev_err(&pdev->dev, "unknown usb instance\n");
- goto fail_io;
- }
+ goto cleanup_hcd_create;
}

- tegra->phy = tegra_usb_phy_open(&pdev->dev, instance, hcd->regs,
- pdata->phy_config);
- if (IS_ERR(tegra->phy)) {
- dev_err(&pdev->dev, "Failed to open USB phy\n");
- err = -ENXIO;
- goto fail_io;
+ err = usb_phy_init(hcd->phy);
+ if (err) {
+ dev_err(&pdev->dev, "Failed to initialize phy\n");
+ goto cleanup_hcd_create;
}

- hcd->phy = u_phy = &tegra->phy->u_phy;
- usb_phy_init(hcd->phy);
-
u_phy->otg = devm_kzalloc(&pdev->dev, sizeof(struct usb_otg),
GFP_KERNEL);
if (!u_phy->otg) {
dev_err(&pdev->dev, "Failed to alloc memory for otg\n");
err = -ENOMEM;
- goto fail_io;
+ goto cleanup_phy;
}
u_phy->otg->host = hcd_to_bus(hcd);

err = usb_phy_set_suspend(hcd->phy, 0);
if (err) {
dev_err(&pdev->dev, "Failed to power on the phy\n");
- goto fail_phy;
+ goto cleanup_phy;
}

tegra->host_resumed = 1;
@@ -769,7 +753,7 @@ static int tegra_ehci_probe(struct platform_device *pdev)
if (!irq) {
dev_err(&pdev->dev, "Failed to get IRQ\n");
err = -ENODEV;
- goto fail_phy;
+ goto cleanup_phy;
}

if (pdata->operating_mode == TEGRA_USB_OTG) {
@@ -781,10 +765,12 @@ static int tegra_ehci_probe(struct platform_device *pdev)
tegra->transceiver = ERR_PTR(-ENODEV);
}

+ platform_set_drvdata(pdev, tegra);
+
err = usb_add_hcd(hcd, irq, IRQF_SHARED);
if (err) {
dev_err(&pdev->dev, "Failed to add USB HCD\n");
- goto fail;
+ goto cleanup_phy;
}

pm_runtime_set_active(&pdev->dev);
@@ -797,15 +783,14 @@ static int tegra_ehci_probe(struct platform_device *pdev)
pm_runtime_put_sync(&pdev->dev);
return err;

-fail:
+cleanup_phy:
if (!IS_ERR(tegra->transceiver))
otg_set_host(tegra->transceiver->otg, NULL);
-fail_phy:
usb_phy_shutdown(hcd->phy);
-fail_io:
- clk_disable_unprepare(tegra->clk);
-fail_clk:
+cleanup_hcd_create:
usb_put_hcd(hcd);
+cleanup_clk:
+ clk_disable_unprepare(tegra->clk);
return err;
}

diff --git a/drivers/usb/phy/phy-tegra-usb.c b/drivers/usb/phy/phy-tegra-usb.c
index dce692a..4d81b19 100644
--- a/drivers/usb/phy/phy-tegra-usb.c
+++ b/drivers/usb/phy/phy-tegra-usb.c
@@ -1,9 +1,11 @@
/*
* Copyright (C) 2010 Google, Inc.
+ * Copyright (C) 2013 NVIDIA Corporation
*
* Author:
* Erik Gilling <[email protected]>
* Benoit Goby <[email protected]>
+ * Venu Byravarasu <[email protected]>
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
@@ -30,9 +32,7 @@
#include <linux/usb/ulpi.h>
#include <asm/mach-types.h>
#include <linux/usb/tegra_usb_phy.h>
-
-#define TEGRA_USB_BASE 0xC5000000
-#define TEGRA_USB_SIZE SZ_16K
+#include <linux/module.h>

#define ULPI_VIEWPORT 0x170

@@ -198,32 +198,15 @@ static struct tegra_utmip_config utmip_default[] = {

static int utmip_pad_open(struct tegra_usb_phy *phy)
{
- phy->pad_clk = clk_get_sys("utmip-pad", NULL);
+ phy->pad_clk = devm_clk_get(phy->dev, "utmi-pads");
if (IS_ERR(phy->pad_clk)) {
pr_err("%s: can't get utmip pad clock\n", __func__);
return PTR_ERR(phy->pad_clk);
}

- if (phy->is_legacy_phy) {
- phy->pad_regs = phy->regs;
- } else {
- phy->pad_regs = ioremap(TEGRA_USB_BASE, TEGRA_USB_SIZE);
- if (!phy->pad_regs) {
- pr_err("%s: can't remap usb registers\n", __func__);
- clk_put(phy->pad_clk);
- return -ENOMEM;
- }
- }
return 0;
}

-static void utmip_pad_close(struct tegra_usb_phy *phy)
-{
- if (!phy->is_legacy_phy)
- iounmap(phy->pad_regs);
- clk_put(phy->pad_clk);
-}
-
static void utmip_pad_power_on(struct tegra_usb_phy *phy)
{
unsigned long val, flags;
@@ -614,76 +597,11 @@ static int ulpi_phy_power_off(struct tegra_usb_phy *phy)
return gpio_direction_output(phy->reset_gpio, 0);
}

-static int tegra_phy_init(struct usb_phy *x)
-{
- struct tegra_usb_phy *phy = container_of(x, struct tegra_usb_phy, u_phy);
- struct tegra_ulpi_config *ulpi_config;
- int err;
-
- if (phy->is_ulpi_phy) {
- ulpi_config = phy->config;
- phy->clk = clk_get_sys(NULL, ulpi_config->clk);
- if (IS_ERR(phy->clk)) {
- pr_err("%s: can't get ulpi clock\n", __func__);
- return PTR_ERR(phy->clk);
- }
-
- phy->reset_gpio =
- of_get_named_gpio(phy->dev->of_node,
- "nvidia,phy-reset-gpio", 0);
- if (!gpio_is_valid(phy->reset_gpio)) {
- dev_err(phy->dev, "invalid gpio: %d\n",
- phy->reset_gpio);
- err = phy->reset_gpio;
- goto cleanup_clk_get;
- }
-
- err = gpio_request(phy->reset_gpio, "ulpi_phy_reset_b");
- if (err < 0) {
- dev_err(phy->dev, "request failed for gpio: %d\n",
- phy->reset_gpio);
- goto cleanup_clk_get;
- }
-
- err = gpio_direction_output(phy->reset_gpio, 0);
- if (err < 0) {
- dev_err(phy->dev, "gpio %d direction not set to output\n",
- phy->reset_gpio);
- goto cleanup_gpio_req;
- }
-
- phy->ulpi = otg_ulpi_create(&ulpi_viewport_access_ops, 0);
- if (!phy->ulpi) {
- dev_err(phy->dev, "otg_ulpi_create returned err\n");
- err = -ENOMEM;
- goto cleanup_gpio_req;
- }
-
- phy->ulpi->io_priv = phy->regs + ULPI_VIEWPORT;
- } else {
- err = utmip_pad_open(phy);
- if (err < 0)
- return err;
- }
- return 0;
-cleanup_gpio_req:
- gpio_free(phy->reset_gpio);
-cleanup_clk_get:
- clk_put(phy->clk);
- return err;
-}
-
static void tegra_usb_phy_close(struct usb_phy *x)
{
struct tegra_usb_phy *phy = container_of(x, struct tegra_usb_phy, u_phy);

- if (phy->is_ulpi_phy)
- clk_put(phy->clk);
- else
- utmip_pad_close(phy);
clk_disable_unprepare(phy->pll_u);
- clk_put(phy->pll_u);
- kfree(phy);
}

static int tegra_usb_phy_power_on(struct tegra_usb_phy *phy)
@@ -711,58 +629,63 @@ static int tegra_usb_phy_suspend(struct usb_phy *x, int suspend)
return tegra_usb_phy_power_on(phy);
}

-struct tegra_usb_phy *tegra_usb_phy_open(struct device *dev, int instance,
- void __iomem *regs, void *config)
+static int ulpi_open(struct tegra_usb_phy *phy)
{
- struct tegra_usb_phy *phy;
- unsigned long parent_rate;
- int i;
int err;
- struct device_node *np = dev->of_node;

- phy = kzalloc(sizeof(struct tegra_usb_phy), GFP_KERNEL);
- if (!phy)
- return ERR_PTR(-ENOMEM);
+ phy->clk = devm_clk_get(phy->dev, "ulpi-link");
+ if (IS_ERR(phy->clk)) {
+ pr_err("%s: can't get ulpi clock\n", __func__);
+ return PTR_ERR(phy->clk);
+ }

- phy->instance = instance;
- phy->regs = regs;
- phy->config = config;
- phy->dev = dev;
- phy->is_legacy_phy =
- of_property_read_bool(np, "nvidia,has-legacy-mode");
- err = of_property_match_string(np, "phy_type", "ulpi");
- if (err < 0)
- phy->is_ulpi_phy = false;
- else
- phy->is_ulpi_phy = true;
+ err = devm_gpio_request(phy->dev, phy->reset_gpio, "ulpi_phy_reset_b");
+ if (err < 0) {
+ dev_err(phy->dev, "request failed for gpio: %d\n",
+ phy->reset_gpio);
+ return err;
+ }

- err = of_property_match_string(np, "dr_mode", "otg");
+ err = gpio_direction_output(phy->reset_gpio, 0);
if (err < 0) {
- err = of_property_match_string(np, "dr_mode", "peripheral");
- if (err < 0)
- phy->mode = TEGRA_USB_PHY_MODE_HOST;
+ dev_err(phy->dev, "gpio %d direction not set to output\n",
+ phy->reset_gpio);
+ return err;
+ }
+
+ phy->ulpi = otg_ulpi_create(&ulpi_viewport_access_ops, 0);
+ if (!phy->ulpi) {
+ dev_err(phy->dev, "otg_ulpi_create returned err\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)
+{
+ unsigned long parent_rate;
+ int i;
+ int err;
+
+ if (!phy->is_ulpi_phy) {
+ if (phy->is_legacy_phy)
+ phy->config = &utmip_default[0];
else
- phy->mode = TEGRA_USB_PHY_MODE_DEVICE;
- } else
- phy->mode = TEGRA_USB_PHY_MODE_OTG;
-
- if (!phy->config) {
- if (phy->is_ulpi_phy) {
- pr_err("%s: ulpi phy configuration missing", __func__);
- err = -EINVAL;
- goto err0;
- } else {
- phy->config = &utmip_default[instance];
- }
+ phy->config = &utmip_default[2];
}

- phy->pll_u = clk_get_sys(NULL, "pll_u");
+ phy->pll_u = devm_clk_get(phy->dev, "pll_u");
if (IS_ERR(phy->pll_u)) {
pr_err("Can't get pll_u clock\n");
- err = PTR_ERR(phy->pll_u);
- goto err0;
+ return PTR_ERR(phy->pll_u);
}
- clk_prepare_enable(phy->pll_u);
+
+ err = clk_prepare_enable(phy->pll_u);
+ if (err)
+ return err;

parent_rate = clk_get_rate(clk_get_parent(phy->pll_u));
for (i = 0; i < ARRAY_SIZE(tegra_freq_table); i++) {
@@ -774,23 +697,22 @@ struct tegra_usb_phy *tegra_usb_phy_open(struct device *dev, int instance,
if (!phy->freq) {
pr_err("invalid pll_u parent rate %ld\n", parent_rate);
err = -EINVAL;
- goto err1;
+ goto fail;
}

- phy->u_phy.init = tegra_phy_init;
- phy->u_phy.shutdown = tegra_usb_phy_close;
- phy->u_phy.set_suspend = tegra_usb_phy_suspend;
+ if (phy->is_ulpi_phy)
+ err = ulpi_open(phy);
+ else
+ err = utmip_pad_open(phy);
+ if (err < 0)
+ goto fail;

- return phy;
+ return 0;

-err1:
+fail:
clk_disable_unprepare(phy->pll_u);
- clk_put(phy->pll_u);
-err0:
- kfree(phy);
- return ERR_PTR(err);
+ return err;
}
-EXPORT_SYMBOL_GPL(tegra_usb_phy_open);

void tegra_usb_phy_preresume(struct usb_phy *x)
{
@@ -829,3 +751,121 @@ void tegra_ehci_phy_restore_end(struct usb_phy *x)
}
EXPORT_SYMBOL_GPL(tegra_ehci_phy_restore_end);

+static int tegra_usb_phy_probe(struct platform_device *pdev)
+{
+ struct resource *res;
+ struct tegra_usb_phy *tegra_phy = NULL;
+ struct device_node *np = pdev->dev.of_node;
+ int err;
+
+ tegra_phy = devm_kzalloc(&pdev->dev, sizeof(*tegra_phy), GFP_KERNEL);
+ if (!tegra_phy) {
+ dev_err(&pdev->dev, "unable to allocate memory for USB2 PHY\n");
+ return -ENOMEM;
+ }
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res) {
+ dev_err(&pdev->dev, "Failed to get I/O memory\n");
+ return -ENXIO;
+ }
+
+ tegra_phy->regs = devm_ioremap(&pdev->dev, res->start,
+ resource_size(res));
+ if (!tegra_phy->regs) {
+ dev_err(&pdev->dev, "Failed to remap I/O memory\n");
+ return -ENOMEM;
+ }
+
+ tegra_phy->is_legacy_phy =
+ of_property_read_bool(np, "nvidia,has-legacy-mode");
+
+ err = of_property_match_string(np, "phy_type", "ulpi");
+ if (err < 0) {
+ tegra_phy->is_ulpi_phy = false;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+ if (!res) {
+ dev_err(&pdev->dev, "Failed to get UTMI Pad regs\n");
+ return -ENXIO;
+ }
+
+ tegra_phy->pad_regs = devm_ioremap(&pdev->dev, res->start,
+ resource_size(res));
+ if (!tegra_phy->regs) {
+ dev_err(&pdev->dev, "Failed to remap UTMI Pad regs\n");
+ return -ENOMEM;
+ }
+ } else {
+ 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;
+ }
+ }
+
+ err = of_property_match_string(np, "dr_mode", "otg");
+ if (err < 0) {
+ err = of_property_match_string(np, "dr_mode", "peripheral");
+ if (err < 0)
+ tegra_phy->mode = TEGRA_USB_PHY_MODE_HOST;
+ else
+ tegra_phy->mode = TEGRA_USB_PHY_MODE_DEVICE;
+ } else
+ tegra_phy->mode = TEGRA_USB_PHY_MODE_OTG;
+
+ tegra_phy->dev = &pdev->dev;
+ err = tegra_usb_phy_init(tegra_phy);
+ if (err < 0)
+ return err;
+
+ tegra_phy->u_phy.shutdown = tegra_usb_phy_close;
+ tegra_phy->u_phy.set_suspend = tegra_usb_phy_suspend;
+
+ dev_set_drvdata(&pdev->dev, tegra_phy);
+ return 0;
+}
+
+static struct of_device_id tegra_usb_phy_id_table[] = {
+ { .compatible = "nvidia,tegra20-usb-phy", },
+ { },
+};
+MODULE_DEVICE_TABLE(of, tegra_usb_phy_id_table);
+
+static struct platform_driver tegra_usb_phy_driver = {
+ .probe = tegra_usb_phy_probe,
+ .driver = {
+ .name = "tegra-phy",
+ .owner = THIS_MODULE,
+ .of_match_table = of_match_ptr(tegra_usb_phy_id_table),
+ },
+};
+module_platform_driver(tegra_usb_phy_driver);
+
+static int tegra_usb_phy_match(struct device *dev, void *data)
+{
+ struct tegra_usb_phy *tegra_phy = dev_get_drvdata(dev);
+ struct device_node *dn = data;
+
+ return (tegra_phy->dev->of_node == dn) ? 1 : 0;
+}
+
+struct usb_phy *tegra_usb_get_phy(struct device_node *dn)
+{
+ struct device *dev;
+ struct tegra_usb_phy *tegra_phy;
+
+ dev = driver_find_device(&tegra_usb_phy_driver.driver, NULL, dn,
+ tegra_usb_phy_match);
+ if (!dev)
+ return ERR_PTR(-EPROBE_DEFER);
+
+ tegra_phy = dev_get_drvdata(dev);
+
+ return &tegra_phy->u_phy;
+}
+EXPORT_SYMBOL_GPL(tegra_usb_get_phy);
diff --git a/include/linux/usb/tegra_usb_phy.h b/include/linux/usb/tegra_usb_phy.h
index 6cfb8f1..0cd15d2 100644
--- a/include/linux/usb/tegra_usb_phy.h
+++ b/include/linux/usb/tegra_usb_phy.h
@@ -65,8 +65,7 @@ struct tegra_usb_phy {
int reset_gpio;
};

-struct tegra_usb_phy *tegra_usb_phy_open(struct device *dev, int instance,
- void __iomem *regs, void *config);
+struct usb_phy *tegra_usb_get_phy(struct device_node *dn);

void tegra_usb_phy_preresume(struct usb_phy *phy);

--
1.7.0.4

2013-05-10 14:03:50

by Venu Byravarasu

[permalink] [raw]
Subject: [PATCH v3 10/10] Usb: Move PORTSC access to PHY

Changes with this patch:
1. As PHY is being registered as separate platform driver & EHCI Tegra
is no more calling PHY open, moved tegra_ehci_set_pts & tegra_ehci_set_phcd
functions to PHY driver,

2. Removed unused defines for multiple USB port base addresses

Signed-off-by: Venu Byravarasu <[email protected]>
---
This is a new patch being added into the series, to address the revert done
with patch#4 of the series.

drivers/usb/host/ehci-tegra.c | 49 -------------------------------------
drivers/usb/phy/phy-tegra-usb.c | 37 +++++++++++++++++++++++++--
include/linux/usb/tegra_usb_phy.h | 4 ---
3 files changed, 34 insertions(+), 56 deletions(-)

diff --git a/drivers/usb/host/ehci-tegra.c b/drivers/usb/host/ehci-tegra.c
index 406abd9..2340d7a 100644
--- a/drivers/usb/host/ehci-tegra.c
+++ b/drivers/usb/host/ehci-tegra.c
@@ -30,15 +30,6 @@
#include <linux/usb/tegra_usb_phy.h>
#include <linux/clk/tegra.h>

-#define TEGRA_USB_BASE 0xC5000000
-#define TEGRA_USB2_BASE 0xC5004000
-#define TEGRA_USB3_BASE 0xC5008000
-
-/* PORTSC registers */
-#define TEGRA_USB_PORTSC1 0x184
-#define TEGRA_USB_PORTSC1_PTS(x) (((x) & 0x3) << 30)
-#define TEGRA_USB_PORTSC1_PHCD (1 << 23)
-
#define TEGRA_USB_DMA_ALIGN 32

struct tegra_ehci_hcd {
@@ -608,37 +599,6 @@ static const struct dev_pm_ops tegra_ehci_pm_ops = {

#endif

-/* Bits of PORTSC1, which will get cleared by writing 1 into them */
-#define TEGRA_PORTSC1_RWC_BITS (PORT_CSC | PORT_PEC | PORT_OCC)
-
-void tegra_ehci_set_pts(struct usb_phy *x, u8 pts_val)
-{
- unsigned long val;
- struct usb_hcd *hcd = bus_to_hcd(x->otg->host);
- void __iomem *base = hcd->regs;
-
- val = readl(base + TEGRA_USB_PORTSC1) & ~TEGRA_PORTSC1_RWC_BITS;
- val &= ~TEGRA_USB_PORTSC1_PTS(3);
- val |= TEGRA_USB_PORTSC1_PTS(pts_val & 3);
- writel(val, base + TEGRA_USB_PORTSC1);
-}
-EXPORT_SYMBOL_GPL(tegra_ehci_set_pts);
-
-void tegra_ehci_set_phcd(struct usb_phy *x, bool enable)
-{
- unsigned long val;
- struct usb_hcd *hcd = bus_to_hcd(x->otg->host);
- void __iomem *base = hcd->regs;
-
- val = readl(base + TEGRA_USB_PORTSC1) & ~TEGRA_PORTSC1_RWC_BITS;
- if (enable)
- val |= TEGRA_USB_PORTSC1_PHCD;
- else
- val &= ~TEGRA_USB_PORTSC1_PHCD;
- writel(val, base + TEGRA_USB_PORTSC1);
-}
-EXPORT_SYMBOL_GPL(tegra_ehci_set_phcd);
-
static u64 tegra_ehci_dma_mask = DMA_BIT_MASK(32);

static int tegra_ehci_probe(struct platform_device *pdev)
@@ -731,15 +691,6 @@ static int tegra_ehci_probe(struct platform_device *pdev)
goto cleanup_hcd_create;
}

- u_phy->otg = devm_kzalloc(&pdev->dev, sizeof(struct usb_otg),
- GFP_KERNEL);
- if (!u_phy->otg) {
- dev_err(&pdev->dev, "Failed to alloc memory for otg\n");
- err = -ENOMEM;
- goto cleanup_phy;
- }
- u_phy->otg->host = hcd_to_bus(hcd);
-
err = usb_phy_set_suspend(hcd->phy, 0);
if (err) {
dev_err(&pdev->dev, "Failed to power on the phy\n");
diff --git a/drivers/usb/phy/phy-tegra-usb.c b/drivers/usb/phy/phy-tegra-usb.c
index 4d81b19..b2a909f 100644
--- a/drivers/usb/phy/phy-tegra-usb.c
+++ b/drivers/usb/phy/phy-tegra-usb.c
@@ -33,6 +33,7 @@
#include <asm/mach-types.h>
#include <linux/usb/tegra_usb_phy.h>
#include <linux/module.h>
+#include <linux/usb/ehci_def.h>

#define ULPI_VIEWPORT 0x170

@@ -196,6 +197,36 @@ static struct tegra_utmip_config utmip_default[] = {
},
};

+/* PORTSC registers */
+#define TEGRA_USB_PORTSC1 0x184
+#define TEGRA_USB_PORTSC1_PTS(x) (((x) & 0x3) << 30)
+#define TEGRA_USB_PORTSC1_PHCD (1 << 23)
+
+/* Bits of PORTSC1, which will get cleared by writing 1 into them */
+#define TEGRA_PORTSC1_RWC_BITS (PORT_CSC | PORT_PEC | PORT_OCC)
+
+static void tegra_ehci_set_pts(void __iomem *base, u8 pts_val)
+{
+ unsigned long val;
+
+ val = readl(base + TEGRA_USB_PORTSC1) & ~TEGRA_PORTSC1_RWC_BITS;
+ val &= ~TEGRA_USB_PORTSC1_PTS(3);
+ val |= TEGRA_USB_PORTSC1_PTS(pts_val & 3);
+ writel(val, base + TEGRA_USB_PORTSC1);
+}
+
+static void tegra_ehci_set_phcd(void __iomem *base, bool enable)
+{
+ unsigned long val;
+
+ val = readl(base + TEGRA_USB_PORTSC1) & ~TEGRA_PORTSC1_RWC_BITS;
+ if (enable)
+ val |= TEGRA_USB_PORTSC1_PHCD;
+ else
+ val &= ~TEGRA_USB_PORTSC1_PHCD;
+ writel(val, base + TEGRA_USB_PORTSC1);
+}
+
static int utmip_pad_open(struct tegra_usb_phy *phy)
{
phy->pad_clk = devm_clk_get(phy->dev, "utmi-pads");
@@ -282,7 +313,7 @@ static void utmi_phy_clk_disable(struct tegra_usb_phy *phy)
val &= ~USB_SUSP_SET;
writel(val, base + USB_SUSP_CTRL);
} else
- tegra_ehci_set_phcd(&phy->u_phy, true);
+ tegra_ehci_set_phcd(base, true);

if (utmi_wait_register(base + USB_SUSP_CTRL, USB_PHY_CLK_VALID, 0) < 0)
pr_err("%s: timeout waiting for phy to stabilize\n", __func__);
@@ -304,7 +335,7 @@ static void utmi_phy_clk_enable(struct tegra_usb_phy *phy)
val &= ~USB_SUSP_CLR;
writel(val, base + USB_SUSP_CTRL);
} else
- tegra_ehci_set_phcd(&phy->u_phy, false);
+ tegra_ehci_set_phcd(base, false);

if (utmi_wait_register(base + USB_SUSP_CTRL, USB_PHY_CLK_VALID,
USB_PHY_CLK_VALID))
@@ -427,7 +458,7 @@ static int utmi_phy_power_on(struct tegra_usb_phy *phy)
utmi_phy_clk_enable(phy);

if (!phy->is_legacy_phy)
- tegra_ehci_set_pts(&phy->u_phy, 0);
+ tegra_ehci_set_pts(base, 0);

return 0;
}
diff --git a/include/linux/usb/tegra_usb_phy.h b/include/linux/usb/tegra_usb_phy.h
index 0cd15d2..d2ca919 100644
--- a/include/linux/usb/tegra_usb_phy.h
+++ b/include/linux/usb/tegra_usb_phy.h
@@ -76,8 +76,4 @@ void tegra_ehci_phy_restore_start(struct usb_phy *phy,

void tegra_ehci_phy_restore_end(struct usb_phy *phy);

-void tegra_ehci_set_pts(struct usb_phy *x, u8 pts_val);
-
-void tegra_ehci_set_phcd(struct usb_phy *x, bool enable);
-
#endif /* __TEGRA_USB_PHY_H */
--
1.7.0.4

2013-05-10 14:03:35

by Venu Byravarasu

[permalink] [raw]
Subject: [PATCH v3 08/10] usb: phy: tegra: Add error handling & clean up.

Check return values from all GPIO APIs and handle errors accordingly.

Remove the call to clk_disable_unprepare(); this function does not
prepare or enable the clock, so the error path should not disable or
unprepare it.

Signed-off-by: Venu Byravarasu <[email protected]>
---
delta from v1:
no changes.

delta from v2:
Fixed checkpatch warnings.


drivers/usb/phy/phy-tegra-usb.c | 50 ++++++++++++++++++++++++++++++--------
1 files changed, 39 insertions(+), 11 deletions(-)

diff --git a/drivers/usb/phy/phy-tegra-usb.c b/drivers/usb/phy/phy-tegra-usb.c
index a2a89a9..dce692a 100644
--- a/drivers/usb/phy/phy-tegra-usb.c
+++ b/drivers/usb/phy/phy-tegra-usb.c
@@ -542,9 +542,17 @@ static int ulpi_phy_power_on(struct tegra_usb_phy *phy)
unsigned long val;
void __iomem *base = phy->regs;

- gpio_direction_output(phy->reset_gpio, 0);
+ ret = gpio_direction_output(phy->reset_gpio, 0);
+ if (ret < 0) {
+ dev_err(phy->dev, "gpio %d not set to 0\n", phy->reset_gpio);
+ return ret;
+ }
msleep(5);
- gpio_direction_output(phy->reset_gpio, 1);
+ ret = gpio_direction_output(phy->reset_gpio, 1);
+ if (ret < 0) {
+ dev_err(phy->dev, "gpio %d not set to 1\n", phy->reset_gpio);
+ return ret;
+ }

clk_prepare_enable(phy->clk);
msleep(1);
@@ -624,24 +632,44 @@ static int tegra_phy_init(struct usb_phy *x)
of_get_named_gpio(phy->dev->of_node,
"nvidia,phy-reset-gpio", 0);
if (!gpio_is_valid(phy->reset_gpio)) {
- pr_err("%s: invalid reset gpio: %d\n", __func__,
+ dev_err(phy->dev, "invalid gpio: %d\n",
+ phy->reset_gpio);
+ err = phy->reset_gpio;
+ goto cleanup_clk_get;
+ }
+
+ err = gpio_request(phy->reset_gpio, "ulpi_phy_reset_b");
+ if (err < 0) {
+ dev_err(phy->dev, "request failed for gpio: %d\n",
phy->reset_gpio);
- err = -EINVAL;
- goto err1;
+ goto cleanup_clk_get;
+ }
+
+ err = gpio_direction_output(phy->reset_gpio, 0);
+ if (err < 0) {
+ dev_err(phy->dev, "gpio %d direction not set to output\n",
+ phy->reset_gpio);
+ goto cleanup_gpio_req;
}
- gpio_request(phy->reset_gpio, "ulpi_phy_reset_b");
- gpio_direction_output(phy->reset_gpio, 0);
+
phy->ulpi = otg_ulpi_create(&ulpi_viewport_access_ops, 0);
+ if (!phy->ulpi) {
+ dev_err(phy->dev, "otg_ulpi_create returned err\n");
+ err = -ENOMEM;
+ goto cleanup_gpio_req;
+ }
+
phy->ulpi->io_priv = phy->regs + ULPI_VIEWPORT;
} else {
err = utmip_pad_open(phy);
if (err < 0)
- goto err1;
+ return err;
}
return 0;
-err1:
- clk_disable_unprepare(phy->pll_u);
- clk_put(phy->pll_u);
+cleanup_gpio_req:
+ gpio_free(phy->reset_gpio);
+cleanup_clk_get:
+ clk_put(phy->clk);
return err;
}

--
1.7.0.4

2013-05-10 14:04:19

by Venu Byravarasu

[permalink] [raw]
Subject: [PATCH v3 05/10] usb: phy: tegra: Get PHY mode using DT

Added a new PHY mode to support OTG.
Obtained Tegra USB PHY mode using DT property.

Signed-off-by: Venu Byravarasu <[email protected]>
---
delta from v1:
replaced gadget with peripheral.

delta from v2:
No change

drivers/usb/host/ehci-tegra.c | 3 +--
drivers/usb/phy/phy-tegra-usb.c | 13 +++++++++++--
include/linux/usb/tegra_usb_phy.h | 3 ++-
3 files changed, 14 insertions(+), 5 deletions(-)

diff --git a/drivers/usb/host/ehci-tegra.c b/drivers/usb/host/ehci-tegra.c
index ed201ae..f4b2164 100644
--- a/drivers/usb/host/ehci-tegra.c
+++ b/drivers/usb/host/ehci-tegra.c
@@ -737,8 +737,7 @@ static int tegra_ehci_probe(struct platform_device *pdev)
}

tegra->phy = tegra_usb_phy_open(&pdev->dev, instance, hcd->regs,
- pdata->phy_config,
- TEGRA_USB_PHY_MODE_HOST);
+ pdata->phy_config);
if (IS_ERR(tegra->phy)) {
dev_err(&pdev->dev, "Failed to open USB phy\n");
err = -ENXIO;
diff --git a/drivers/usb/phy/phy-tegra-usb.c b/drivers/usb/phy/phy-tegra-usb.c
index 5487d38..91b6e29 100644
--- a/drivers/usb/phy/phy-tegra-usb.c
+++ b/drivers/usb/phy/phy-tegra-usb.c
@@ -688,7 +688,7 @@ static int tegra_usb_phy_suspend(struct usb_phy *x, int suspend)
}

struct tegra_usb_phy *tegra_usb_phy_open(struct device *dev, int instance,
- void __iomem *regs, void *config, enum tegra_usb_phy_mode phy_mode)
+ void __iomem *regs, void *config)
{
struct tegra_usb_phy *phy;
unsigned long parent_rate;
@@ -703,7 +703,6 @@ struct tegra_usb_phy *tegra_usb_phy_open(struct device *dev, int instance,
phy->instance = instance;
phy->regs = regs;
phy->config = config;
- phy->mode = phy_mode;
phy->dev = dev;
phy->is_legacy_phy =
of_property_read_bool(np, "nvidia,has-legacy-mode");
@@ -713,6 +712,16 @@ struct tegra_usb_phy *tegra_usb_phy_open(struct device *dev, int instance,
else
phy->is_ulpi_phy = true;

+ err = of_property_match_string(np, "dr_mode", "otg");
+ if (err < 0) {
+ err = of_property_match_string(np, "dr_mode", "peripheral");
+ if (err < 0)
+ phy->mode = TEGRA_USB_PHY_MODE_HOST;
+ else
+ phy->mode = TEGRA_USB_PHY_MODE_DEVICE;
+ } else
+ phy->mode = TEGRA_USB_PHY_MODE_OTG;
+
if (!phy->config) {
if (phy->is_ulpi_phy) {
pr_err("%s: ulpi phy configuration missing", __func__);
diff --git a/include/linux/usb/tegra_usb_phy.h b/include/linux/usb/tegra_usb_phy.h
index 9ebebe9..a7af923 100644
--- a/include/linux/usb/tegra_usb_phy.h
+++ b/include/linux/usb/tegra_usb_phy.h
@@ -42,6 +42,7 @@ enum tegra_usb_phy_port_speed {
enum tegra_usb_phy_mode {
TEGRA_USB_PHY_MODE_DEVICE,
TEGRA_USB_PHY_MODE_HOST,
+ TEGRA_USB_PHY_MODE_OTG,
};

struct tegra_xtal_freq;
@@ -64,7 +65,7 @@ struct tegra_usb_phy {
};

struct tegra_usb_phy *tegra_usb_phy_open(struct device *dev, int instance,
- void __iomem *regs, void *config, enum tegra_usb_phy_mode phy_mode);
+ void __iomem *regs, void *config);

void tegra_usb_phy_preresume(struct usb_phy *phy);

--
1.7.0.4

2013-05-10 14:05:53

by Venu Byravarasu

[permalink] [raw]
Subject: [PATCH v3 07/10] usb: phy: tegra: get ULPI reset GPIO info using DT.

As GPIO information is avail through DT, used it to get Tegra ULPI
reset GPIO number. Added a new member to tegra_usb_phy structure to
store this number.

Signed-off-by: Venu Byravarasu <[email protected]>
---
delta from v1 & v2: no change.

drivers/usb/phy/phy-tegra-usb.c | 25 +++++++++++--------------
include/linux/usb/tegra_usb_phy.h | 1 +
2 files changed, 12 insertions(+), 14 deletions(-)

diff --git a/drivers/usb/phy/phy-tegra-usb.c b/drivers/usb/phy/phy-tegra-usb.c
index 16851e2..a2a89a9 100644
--- a/drivers/usb/phy/phy-tegra-usb.c
+++ b/drivers/usb/phy/phy-tegra-usb.c
@@ -541,11 +541,10 @@ static int ulpi_phy_power_on(struct tegra_usb_phy *phy)
int ret;
unsigned long val;
void __iomem *base = phy->regs;
- struct tegra_ulpi_config *config = phy->config;

- gpio_direction_output(config->reset_gpio, 0);
+ gpio_direction_output(phy->reset_gpio, 0);
msleep(5);
- gpio_direction_output(config->reset_gpio, 1);
+ gpio_direction_output(phy->reset_gpio, 1);

clk_prepare_enable(phy->clk);
msleep(1);
@@ -603,10 +602,8 @@ static int ulpi_phy_power_on(struct tegra_usb_phy *phy)

static int ulpi_phy_power_off(struct tegra_usb_phy *phy)
{
- struct tegra_ulpi_config *config = phy->config;
-
clk_disable(phy->clk);
- return gpio_direction_output(config->reset_gpio, 0);
+ return gpio_direction_output(phy->reset_gpio, 0);
}

static int tegra_phy_init(struct usb_phy *x)
@@ -622,18 +619,18 @@ static int tegra_phy_init(struct usb_phy *x)
pr_err("%s: can't get ulpi clock\n", __func__);
return PTR_ERR(phy->clk);
}
- if (!gpio_is_valid(ulpi_config->reset_gpio))
- ulpi_config->reset_gpio =
- of_get_named_gpio(phy->dev->of_node,
- "nvidia,phy-reset-gpio", 0);
- if (!gpio_is_valid(ulpi_config->reset_gpio)) {
+
+ phy->reset_gpio =
+ of_get_named_gpio(phy->dev->of_node,
+ "nvidia,phy-reset-gpio", 0);
+ if (!gpio_is_valid(phy->reset_gpio)) {
pr_err("%s: invalid reset gpio: %d\n", __func__,
- ulpi_config->reset_gpio);
+ phy->reset_gpio);
err = -EINVAL;
goto err1;
}
- gpio_request(ulpi_config->reset_gpio, "ulpi_phy_reset_b");
- gpio_direction_output(ulpi_config->reset_gpio, 0);
+ gpio_request(phy->reset_gpio, "ulpi_phy_reset_b");
+ gpio_direction_output(phy->reset_gpio, 0);
phy->ulpi = otg_ulpi_create(&ulpi_viewport_access_ops, 0);
phy->ulpi->io_priv = phy->regs + ULPI_VIEWPORT;
} else {
diff --git a/include/linux/usb/tegra_usb_phy.h b/include/linux/usb/tegra_usb_phy.h
index a7af923..6cfb8f1 100644
--- a/include/linux/usb/tegra_usb_phy.h
+++ b/include/linux/usb/tegra_usb_phy.h
@@ -62,6 +62,7 @@ struct tegra_usb_phy {
struct device *dev;
bool is_legacy_phy;
bool is_ulpi_phy;
+ int reset_gpio;
};

struct tegra_usb_phy *tegra_usb_phy_open(struct device *dev, int instance,
--
1.7.0.4

2013-05-10 14:03:17

by Venu Byravarasu

[permalink] [raw]
Subject: [PATCH v3 03/10] ARM: tegra: update device trees for USB binding rework

This patch updates all Tegra board files so that they contain all the
properties required by the updated USB DT binding. Note that this patch
only adds the new properties and does not yet remove the old properties,
in order to maintain bisectability. The old properties will be removed
once the driver has been updated to assume the new bindings.

The only exception is otg property which was removed, as VBUS details
for all the boards are not known. This should not affect for those boards
in any way, as otg is not really supported in Tegra20 USB driver, though
it was set in DT properties.

Signed-off-by: Venu Byravarasu <[email protected]>
---
delta from v1:
1. Fixed voltage regulators were used for vbus-supply
2. Added UTMI PHY timing Parameters to DT.

delta from v2:
1. Removed dr_mode setting to otg, due to:
a. Any ways existing Tegra USB driver does not support OTG.
b. lack of knowledge of all Vbus supplies, on all target platforms.
Once real OTG support is added to Tegra USB driver, then this property can be
set back to otg, for target platforms.

2. All changes related to 'nvidia,phy-reset-gpio' were moved to patch 2 of the
same series.

arch/arm/boot/dts/tegra20-iris-512.dts | 1 -
arch/arm/boot/dts/tegra20-seaboard.dts | 14 +++++++++-
arch/arm/boot/dts/tegra20-trimslice.dts | 13 +++++++++
arch/arm/boot/dts/tegra20-whistler.dts | 26 +++++++++++++++++
arch/arm/boot/dts/tegra20.dtsi | 46 +++++++++++++++++++++++--------
5 files changed, 86 insertions(+), 14 deletions(-)

diff --git a/arch/arm/boot/dts/tegra20-iris-512.dts b/arch/arm/boot/dts/tegra20-iris-512.dts
index 52f1103..b7f71e8 100644
--- a/arch/arm/boot/dts/tegra20-iris-512.dts
+++ b/arch/arm/boot/dts/tegra20-iris-512.dts
@@ -38,7 +38,6 @@

usb@c5000000 {
status = "okay";
- dr_mode = "otg";
};

usb@c5008000 {
diff --git a/arch/arm/boot/dts/tegra20-seaboard.dts b/arch/arm/boot/dts/tegra20-seaboard.dts
index 9dd4f8e..d51e969 100644
--- a/arch/arm/boot/dts/tegra20-seaboard.dts
+++ b/arch/arm/boot/dts/tegra20-seaboard.dts
@@ -566,7 +566,10 @@
usb@c5000000 {
status = "okay";
nvidia,vbus-gpio = <&gpio 24 0>; /* PD0 */
- dr_mode = "otg";
+ };
+
+ usb-phy@c5000000 {
+ vbus-supply = <&vbus_reg>;
};

usb@c5004000 {
@@ -807,6 +810,15 @@
gpio = <&pmic 1 0>;
enable-active-high;
};
+
+ vbus_reg: regulator@3 {
+ compatible = "regulator-fixed";
+ reg = <3>;
+ regulator-name = "vdd_5v0";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ gpio = <&gpio 24 0>; /* PD0 */
+ };
};

sound {
diff --git a/arch/arm/boot/dts/tegra20-trimslice.dts b/arch/arm/boot/dts/tegra20-trimslice.dts
index fd7afd6..85699f0 100644
--- a/arch/arm/boot/dts/tegra20-trimslice.dts
+++ b/arch/arm/boot/dts/tegra20-trimslice.dts
@@ -314,6 +314,10 @@
nvidia,vbus-gpio = <&gpio 170 0>; /* gpio PV2 */
};

+ usb-phy@c5000000 {
+ vbus-supply = <&vbus_reg>;
+ };
+
usb@c5004000 {
status = "okay";
nvidia,phy-reset-gpio = <&gpio 168 1>; /* gpio PV0, active low */
@@ -390,6 +394,15 @@
regulator-max-microvolt = <1800000>;
regulator-always-on;
};
+
+ vbus_reg: regulator@2 {
+ compatible = "regulator-fixed";
+ reg = <2>;
+ regulator-name = "vdd_5v0";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ gpio = <&gpio 170 0>; /* PV2 */
+ };
};

sound {
diff --git a/arch/arm/boot/dts/tegra20-whistler.dts b/arch/arm/boot/dts/tegra20-whistler.dts
index d2567f8..9aec63a 100644
--- a/arch/arm/boot/dts/tegra20-whistler.dts
+++ b/arch/arm/boot/dts/tegra20-whistler.dts
@@ -511,11 +511,19 @@
nvidia,vbus-gpio = <&tca6416 0 0>; /* GPIO_PMU0 */
};

+ usb-phy@c5000000 {
+ vbus-supply = <&vbus_reg1>;
+ };
+
usb@c5008000 {
status = "okay";
nvidia,vbus-gpio = <&tca6416 1 0>; /* GPIO_PMU1 */
};

+ usb-phy@c5008000 {
+ vbus-supply = <&vbus_reg2>;
+ };
+
sdhci@c8000400 {
status = "okay";
cd-gpios = <&gpio 69 1>; /* gpio PI5 */
@@ -568,6 +576,24 @@
regulator-max-microvolt = <5000000>;
regulator-always-on;
};
+
+ vbus_reg1: regulator@2 {
+ compatible = "regulator-fixed";
+ reg = <2>;
+ regulator-name = "vdd_5v0";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ gpio = <&tca6416 0 0>; /* GPIO_PMU0 */
+ };
+
+ vbus_reg2: regulator@3 {
+ compatible = "regulator-fixed";
+ reg = <3>;
+ regulator-name = "vdd_5v0";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ gpio = <&tca6416 1 0>; /* GPIO_PMU1 */
+ };
};

sound {
diff --git a/arch/arm/boot/dts/tegra20.dtsi b/arch/arm/boot/dts/tegra20.dtsi
index 56a9110..62ea419 100644
--- a/arch/arm/boot/dts/tegra20.dtsi
+++ b/arch/arm/boot/dts/tegra20.dtsi
@@ -455,13 +455,23 @@
status = "disabled";
};

- phy1: usb-phy@c5000400 {
+ phy1: usb-phy@c5000000 {
compatible = "nvidia,tegra20-usb-phy";
- reg = <0xc5000400 0x3c00>;
+ reg = <0xc5000000 0x4000 0xc5000000 0x4000>;
phy_type = "utmi";
+ clocks = <&tegra_car 22>,
+ <&tegra_car 127>,
+ <&tegra_car 106>,
+ <&tegra_car 22>;
+ clock-names = "reg", "pll_u", "timer", "utmi-pads";
nvidia,has-legacy-mode;
- clocks = <&tegra_car 22>, <&tegra_car 127>;
- clock-names = "phy", "pll_u";
+ hssync_start_delay = <9>;
+ idle_wait_delay = <17>;
+ elastic_limit = <16>;
+ term_range_adj = <6>;
+ xcvr_setup = <9>;
+ xcvr_lsfslew = <1>;
+ xcvr_lsrslew = <1>;
};

usb@c5004000 {
@@ -474,12 +484,14 @@
status = "disabled";
};

- phy2: usb-phy@c5004400 {
+ phy2: usb-phy@c5004000 {
compatible = "nvidia,tegra20-usb-phy";
- reg = <0xc5004400 0x3c00>;
+ reg = <0xc5004000 0x4000>;
phy_type = "ulpi";
- clocks = <&tegra_car 93>, <&tegra_car 127>;
- clock-names = "phy", "pll_u";
+ clocks = <&tegra_car 58>,
+ <&tegra_car 127>,
+ <&tegra_car 93>;
+ clock-names = "reg", "pll_u", "ulpi-link";
};

usb@c5008000 {
@@ -492,12 +504,22 @@
status = "disabled";
};

- phy3: usb-phy@c5008400 {
+ phy3: usb-phy@c5008000 {
compatible = "nvidia,tegra20-usb-phy";
- reg = <0xc5008400 0x3c00>;
+ reg = <0xc5008000 0x4000 0xc5000000 0x4000>;
phy_type = "utmi";
- clocks = <&tegra_car 22>, <&tegra_car 127>;
- clock-names = "phy", "pll_u";
+ clocks = <&tegra_car 59>,
+ <&tegra_car 127>,
+ <&tegra_car 106>,
+ <&tegra_car 22>;
+ clock-names = "reg", "pll_u", "timer", "utmi-pads";
+ hssync_start_delay = <9>;
+ idle_wait_delay = <17>;
+ elastic_limit = <16>;
+ term_range_adj = <6>;
+ xcvr_setup = <9>;
+ xcvr_lsfslew = <2>;
+ xcvr_lsrslew = <2>;
};

sdhci@c8000000 {
--
1.7.0.4

2013-05-10 14:03:15

by Venu Byravarasu

[permalink] [raw]
Subject: [PATCH v3 02/10] arm: dt: Tegra20: Modify ULPI reset GPIO properties

changes with this patch:
1. All Tegra20 ULPI reset GPIO DT properties are modified to indicate active
low nature of the GPIO.
2. Placed USB PHY DT node immediately below the EHCI controller DT nodes
and corrected reg value in the name of USB PHY DT node.

Signed-off-by: Venu Byravarasu <[email protected]>
---
Created this patch as per comments received at:
http://marc.info/?l=linux-usb&m=136501761810344&w=2

arch/arm/boot/dts/tegra20-colibri-512.dtsi | 6 +++++-
arch/arm/boot/dts/tegra20-harmony.dts | 10 +++++-----
arch/arm/boot/dts/tegra20-paz00.dts | 10 +++++-----
arch/arm/boot/dts/tegra20-seaboard.dts | 10 +++++-----
arch/arm/boot/dts/tegra20-trimslice.dts | 10 +++++-----
arch/arm/boot/dts/tegra20-ventana.dts | 10 +++++-----
6 files changed, 30 insertions(+), 26 deletions(-)

diff --git a/arch/arm/boot/dts/tegra20-colibri-512.dtsi b/arch/arm/boot/dts/tegra20-colibri-512.dtsi
index a573b94..c12af78 100644
--- a/arch/arm/boot/dts/tegra20-colibri-512.dtsi
+++ b/arch/arm/boot/dts/tegra20-colibri-512.dtsi
@@ -449,7 +449,11 @@

usb@c5004000 {
status = "okay";
- nvidia,phy-reset-gpio = <&gpio 169 0>; /* gpio PV1 */
+ nvidia,phy-reset-gpio = <&gpio 169 1>; /* gpio PV1, active low */
+ };
+
+ usb-phy@c5004000 {
+ nvidia,phy-reset-gpio = <&gpio 169 1>; /* gpio PV1, active low */
};

sdhci@c8000600 {
diff --git a/arch/arm/boot/dts/tegra20-harmony.dts b/arch/arm/boot/dts/tegra20-harmony.dts
index e7d5de4..e84f3f6 100644
--- a/arch/arm/boot/dts/tegra20-harmony.dts
+++ b/arch/arm/boot/dts/tegra20-harmony.dts
@@ -430,15 +430,15 @@

usb@c5004000 {
status = "okay";
- nvidia,phy-reset-gpio = <&gpio 169 0>; /* gpio PV1 */
+ nvidia,phy-reset-gpio = <&gpio 169 1>; /* gpio PV1, active low */
};

- usb@c5008000 {
- status = "okay";
+ usb-phy@c5004000 {
+ nvidia,phy-reset-gpio = <&gpio 169 1>; /* gpio PV1, active low */
};

- usb-phy@c5004400 {
- nvidia,phy-reset-gpio = <&gpio 169 0>; /* gpio PV1 */
+ usb@c5008000 {
+ status = "okay";
};

sdhci@c8000200 {
diff --git a/arch/arm/boot/dts/tegra20-paz00.dts b/arch/arm/boot/dts/tegra20-paz00.dts
index e3e0c99..e9ac2a9 100644
--- a/arch/arm/boot/dts/tegra20-paz00.dts
+++ b/arch/arm/boot/dts/tegra20-paz00.dts
@@ -429,15 +429,15 @@

usb@c5004000 {
status = "okay";
- nvidia,phy-reset-gpio = <&gpio 168 0>; /* gpio PV0 */
+ nvidia,phy-reset-gpio = <&gpio 168 1>; /* gpio PV0, active low */
};

- usb@c5008000 {
- status = "okay";
+ usb-phy@c5004000 {
+ nvidia,phy-reset-gpio = <&gpio 168 1>; /* gpio PV0, active low */
};

- usb-phy@c5004400 {
- nvidia,phy-reset-gpio = <&gpio 168 0>; /* gpio PV0 */
+ usb@c5008000 {
+ status = "okay";
};

sdhci@c8000000 {
diff --git a/arch/arm/boot/dts/tegra20-seaboard.dts b/arch/arm/boot/dts/tegra20-seaboard.dts
index cee4c34..9dd4f8e 100644
--- a/arch/arm/boot/dts/tegra20-seaboard.dts
+++ b/arch/arm/boot/dts/tegra20-seaboard.dts
@@ -571,15 +571,15 @@

usb@c5004000 {
status = "okay";
- nvidia,phy-reset-gpio = <&gpio 169 0>; /* gpio PV1 */
+ nvidia,phy-reset-gpio = <&gpio 169 1>; /* gpio PV1, active low */
};

- usb@c5008000 {
- status = "okay";
+ usb-phy@c5004000 {
+ nvidia,phy-reset-gpio = <&gpio 169 1>; /* gpio PV1, active low */
};

- usb-phy@c5004400 {
- nvidia,phy-reset-gpio = <&gpio 169 0>; /* gpio PV1 */
+ usb@c5008000 {
+ status = "okay";
};

sdhci@c8000000 {
diff --git a/arch/arm/boot/dts/tegra20-trimslice.dts b/arch/arm/boot/dts/tegra20-trimslice.dts
index 9cc78a1..fd7afd6 100644
--- a/arch/arm/boot/dts/tegra20-trimslice.dts
+++ b/arch/arm/boot/dts/tegra20-trimslice.dts
@@ -316,15 +316,15 @@

usb@c5004000 {
status = "okay";
- nvidia,phy-reset-gpio = <&gpio 168 0>; /* gpio PV0 */
+ nvidia,phy-reset-gpio = <&gpio 168 1>; /* gpio PV0, active low */
};

- usb@c5008000 {
- status = "okay";
+ usb-phy@c5004000 {
+ nvidia,phy-reset-gpio = <&gpio 168 1>; /* gpio PV0, active low */
};

- usb-phy@c5004400 {
- nvidia,phy-reset-gpio = <&gpio 168 0>; /* gpio PV0 */
+ usb@c5008000 {
+ status = "okay";
};

sdhci@c8000000 {
diff --git a/arch/arm/boot/dts/tegra20-ventana.dts b/arch/arm/boot/dts/tegra20-ventana.dts
index dd38f1f..a75a0e7 100644
--- a/arch/arm/boot/dts/tegra20-ventana.dts
+++ b/arch/arm/boot/dts/tegra20-ventana.dts
@@ -507,15 +507,15 @@

usb@c5004000 {
status = "okay";
- nvidia,phy-reset-gpio = <&gpio 169 0>; /* gpio PV1 */
+ nvidia,phy-reset-gpio = <&gpio 169 1>; /* gpio PV1, active low */
};

- usb@c5008000 {
- status = "okay";
+ usb-phy@c5004000 {
+ nvidia,phy-reset-gpio = <&gpio 169 1>; /* gpio PV1, active low */
};

- usb-phy@c5004400 {
- nvidia,phy-reset-gpio = <&gpio 169 0>; /* gpio PV1 */
+ usb@c5008000 {
+ status = "okay";
};

sdhci@c8000000 {
--
1.7.0.4

2013-05-10 14:26:29

by Alan Stern

[permalink] [raw]
Subject: Re: [PATCH v3 04/10] Revert "usb: phy: tegra: don't call into tegra-ehci directly"

On Fri, 10 May 2013, Venu Byravarasu wrote:

> This reverts commit ee5d5499edb94cd03738a52a7e234b139da8fd72.
>
> Signed-off-by: Venu Byravarasu <[email protected]>
> ---
> As PHY is being registered as separate driver, solution proposed with
> this patch cannot work anymore.
> Hence pushed patch 10 of this series to address the issue.

You can't just revert a change like this -- doing so will recreate the
original problem that ee5d5499ed was meant to fix.

You have to fix the problem _first_. Then you can revert that commit.

Alan Stern

2013-05-10 18:05:33

by Alan Stern

[permalink] [raw]
Subject: Re: [PATCH v3 04/10] Revert "usb: phy: tegra: don't call into tegra-ehci directly"

On Fri, 10 May 2013, BVG Rao wrote:

> On 10 May 2013 19:56, "Alan Stern" <[email protected]> wrote:
> >
> > On Fri, 10 May 2013, Venu Byravarasu wrote:
> >
> > > This reverts commit ee5d5499edb94cd03738a52a7e234b139da8fd72.
> > >
> > > Signed-off-by: Venu Byravarasu <[email protected]>
> > > ---
> > > As PHY is being registered as separate driver, solution proposed with
> > > this patch cannot work anymore.
> > > Hence pushed patch 10 of this series to address the issue.
> >
> > You can't just revert a change like this -- doing so will recreate the
> > original problem that ee5d5499ed was meant to fix.
> >
> > You have to fix the problem _first_. Then you can revert that commit.
>
> Hi Alan,
>
> I addressed that as part of patch 10 of the series.

I know -- that's what I was complaining about. Patch 4 reverts the old
fix, and the new fix isn't added until patch 10. So anybody who builds
a kernel using only patches 1 - 5 (for example) will end up with a
broken system. This can easily happen during bisection testing.

You need to add the new fix either before or in the same patch as where
the old fix is reverted.

Alan Stern

2013-05-10 18:06:44

by Sergei Shtylyov

[permalink] [raw]
Subject: Re: [PATCH v3 08/10] usb: phy: tegra: Add error handling & clean up.

Hello.

On 05/10/2013 05:54 PM, Venu Byravarasu wrote:

> Check return values from all GPIO APIs and handle errors accordingly.
>
> Remove the call to clk_disable_unprepare(); this function does not
> prepare or enable the clock, so the error path should not disable or
> unprepare it.
>
> Signed-off-by: Venu Byravarasu <[email protected]>
[...]
> diff --git a/drivers/usb/phy/phy-tegra-usb.c b/drivers/usb/phy/phy-tegra-usb.c
> index a2a89a9..dce692a 100644
> --- a/drivers/usb/phy/phy-tegra-usb.c
> +++ b/drivers/usb/phy/phy-tegra-usb.c
[...]
> @@ -624,24 +632,44 @@ static int tegra_phy_init(struct usb_phy *x)
[...]
> phy->ulpi = otg_ulpi_create(&ulpi_viewport_access_ops, 0);
> + if (!phy->ulpi) {
> + dev_err(phy->dev, "otg_ulpi_create returned err\n");

Rather "returned NULL".

WBR, Sergei

2013-05-10 20:04:31

by Stephen Warren

[permalink] [raw]
Subject: Re: [PATCH v3 10/10] Usb: Move PORTSC access to PHY

On 05/10/2013 07:54 AM, Venu Byravarasu wrote:
> Changes with this patch:
> 1. As PHY is being registered as separate platform driver & EHCI Tegra
> is no more calling PHY open, moved tegra_ehci_set_pts & tegra_ehci_set_phcd
> functions to PHY driver,
>
> 2. Removed unused defines for multiple USB port base addresses

This patch (mostly?) is a revert of bbdabdb "usb: add APIs to access
host registers from Tegra PHY". I don't think we want to revert this[1].

Instead, once patch 9/10 in this series is applied, the Tegra EHCI
module should no longer directly reference any symbols in the Tegra USB
PHY module. This is because the functions exposed by the Tegra PHY
module are now accessed using the new standard PHY APIs, rather than
directly by symbol name.

Assuming that's true, it is then permissible for the Tegra PHY module to
once again directly reference symbols exported by the Tegra EHCI module.
So, instead of moving the functions from the EHCI code to the PHY code,
keep them in the EHCI code, and call them from the PHY code, but call
them by function name instead of by function pointer. That way, there's
no need to pass the function pointers during initialization.

You will have to roll that change into patch 9/10 to make git bisect work.


[1] The background is that NVIDIA HW has added some non-standard
register bits to the PORTSC register, related to PHY control. The PHY
driver needs to control those bits, but they're in the EHCI register
space. Since the non-standard bits are controlled by read-modify-write,
the EHCI driver should implement the register accesses, so the it can
implement locking against its own read-modify-write of that register if
required.

2013-05-13 17:17:25

by Stephen Warren

[permalink] [raw]
Subject: Re: [PATCH v3 01/10] ARM: tegra: finalize USB EHCI and PHY bindings

On 05/10/2013 07:54 AM, Venu Byravarasu wrote:
> The existing Tegra USB bindings have a few issues:
>
> 1) Many properties are documented as being part of the EHCI controller
> node, yet they apply more to the PHY device. They should be moved.
>
> 2) Some registers in PHY1 are shared with PHY3, and hence PHY3 needs a
> reg entry to point at PHY1's register space. We can't assume the PHY1
> driver is present, so the PHY3 driver will directly access those
> registers.
>
> 3) The list of clocks required by the PHY was missing some required
> entries.
>
> 4) UTMI PHY Timing parameters are added
>
> 5) VBUS control is now specified using a regulator rather than a plain GPIO
>
> 6) Added nvidia,is-wired property to indicate whether the device is
> hard wired on the board, or pluggable.
>
> This patch fixes the binding definition to resolve these issues.

> diff --git a/Documentation/devicetree/bindings/usb/nvidia,tegra20-usb-phy.txt b/Documentation/devicetree/bindings/usb/nvidia,tegra20-usb-phy.txt

> + the USB controller.
> + - nvidia,is-wired : boolean. Indicates whether we can do certain kind of power
> + optimizations for the devices that are always connected. e.g. modem.
> + - dr_mode : dual role mode. Indicates the working mode for the PHY. Can be
> + "host", "peripheral", or "otg". Defaults to "host" if not defined.
> + host means this is a host controller
> + peripheral means it is device controller
> + otg means it can operate as either ("on the go")

Nit: Please leave a blank line here, to separate the sections/lists.

> +Required properties for dr_mode == otg:
> + - vbus-supply: regulator for VBUS
> \ No newline at end of file

Nit: Since you're reposting this series for other reasons, I'd like to
fix that "No newline at end of file"; please add a newline here.

2013-05-13 17:30:00

by Stephen Warren

[permalink] [raw]
Subject: Re: [PATCH v3 03/10] ARM: tegra: update device trees for USB binding rework

On 05/10/2013 07:54 AM, Venu Byravarasu wrote:
> This patch updates all Tegra board files so that they contain all the
> properties required by the updated USB DT binding. Note that this patch
> only adds the new properties and does not yet remove the old properties,
> in order to maintain bisectability. The old properties will be removed
> once the driver has been updated to assume the new bindings.
>
> The only exception is otg property which was removed, as VBUS details
> for all the boards are not known. This should not affect for those boards
> in any way, as otg is not really supported in Tegra20 USB driver, though

I would change "really" to "yet" here. I hope one day it will be...

> delta from v2:
> 1. Removed dr_mode setting to otg, due to:
> a. Any ways existing Tegra USB driver does not support OTG.

The DT should be describing the HW, and not be related to what some
particular driver currently supports...

> b. lack of knowledge of all Vbus supplies, on all target platforms.

Hence, this part of the change should only be applied to those boards
where we don't know the details of the VBUS supply. For example, Iris
512. For Seaboard, we do know all the required information, so there's
no need to make this change.

> diff --git a/arch/arm/boot/dts/tegra20-seaboard.dts b/arch/arm/boot/dts/tegra20-seaboard.dts

> usb@c5000000 {
> status = "okay";
> nvidia,vbus-gpio = <&gpio 24 0>; /* PD0 */
> - dr_mode = "otg";

You don't need to make that change ...

> + };
> +
> + usb-phy@c5000000 {
> + vbus-supply = <&vbus_reg>;

Since we have all the details we need in order to define vbus-supply here.

> diff --git a/arch/arm/boot/dts/tegra20.dtsi b/arch/arm/boot/dts/tegra20.dtsi

> - phy1: usb-phy@c5000400 {
> + phy1: usb-phy@c5000000 {

One last change throughout this file: the PHY nodes in tegra20.dtsi
should all be marked with:

status = "disabled";

... just like the EHCI nodes already are. This ensures that the devices
aren't activated on boards where those PHYs and EHCI controllers are not
used.

You will also need to add:

status = "okay";

to the top of all PHY nodes in all board .dts files where those PHYs are
used; you can tell which boards need them because those boards will also
set that status property for the relevant EHCI nodes.

2013-05-13 17:30:19

by Stephen Warren

[permalink] [raw]
Subject: Re: [PATCH v3 02/10] arm: dt: Tegra20: Modify ULPI reset GPIO properties

On 05/10/2013 07:54 AM, Venu Byravarasu wrote:
> changes with this patch:

Nit: You can simply delete the line above; the patch description should
always describe the changes in the patch it's describing!