diff options
author | Henry Lin <henryl@nvidia.com> | 2013-09-16 14:15:25 +0800 |
---|---|---|
committer | Bharat Nihalani <bnihalani@nvidia.com> | 2013-10-04 08:36:20 -0700 |
commit | 728fac1d7b7d91ad32ea9ec58da35c9464eed5fd (patch) | |
tree | 0e7b20392e7bbbdabfcf8325eb8e16f076d6bedf /drivers/usb/host/xhci-tegra.c | |
parent | 4d59c84dda7b8cd92755063a261057ca6143ca87 (diff) |
xhci: tegra: only enable vbus owned by xusb
The vbus regulators are shared between xhci and echi host
controller. Only the port owner should enable corresponding
vbus regulator.
Bug 1348463
Change-Id: I77ad19505869e98ae47f1ef36956e8312b5f2e4e
Signed-off-by: Henry Lin <henryl@nvidia.com>
Reviewed-on: http://git-master/r/281337
Reviewed-by: Bharat Nihalani <bnihalani@nvidia.com>
Tested-by: Bharat Nihalani <bnihalani@nvidia.com>
Diffstat (limited to 'drivers/usb/host/xhci-tegra.c')
-rw-r--r-- | drivers/usb/host/xhci-tegra.c | 128 |
1 files changed, 49 insertions, 79 deletions
diff --git a/drivers/usb/host/xhci-tegra.c b/drivers/usb/host/xhci-tegra.c index d54d83f48469..bb8d7610e41c 100644 --- a/drivers/usb/host/xhci-tegra.c +++ b/drivers/usb/host/xhci-tegra.c @@ -364,9 +364,8 @@ struct tegra_xhci_hcd { u32 cmd_type; u32 cmd_data; - struct regulator *xusb_s5p0v_reg; - struct regulator *xusb_s5p0v1_reg; - struct regulator *xusb_s5p0v2_reg; + struct regulator *xusb_utmi_vbus_regs[XUSB_UTMI_COUNT]; + struct regulator *xusb_s1p05v_reg; struct regulator *xusb_s3p3v_reg; struct regulator *xusb_s1p8v_reg; @@ -1452,6 +1451,7 @@ static int tegra_xusb_regulator_init(struct tegra_xhci_hcd *tegra, struct platform_device *pdev) { struct tegra_xusb_regulator_name *supply = &tegra->bdata->supply; + int i; int err = 0; tegra->xusb_s3p3v_reg = @@ -1470,24 +1470,33 @@ static int tegra_xusb_regulator_init(struct tegra_xhci_hcd *tegra, } } - if ((tegra->bdata->portmap & TEGRA_XUSB_USB2_P0) && - !tegra->transceiver) { - tegra->xusb_s5p0v_reg = devm_regulator_get(&pdev->dev, - supply->s5p0v); - if (IS_ERR(tegra->xusb_s5p0v_reg)) { - dev_err(&pdev->dev, "5p0v regulator not found: %ld." - , PTR_ERR(tegra->xusb_s5p0v_reg)); - err = PTR_ERR(tegra->xusb_s5p0v_reg); - goto err_put_s3p3v_reg; - } else { - err = regulator_enable(tegra->xusb_s5p0v_reg); - if (err < 0) { + /* enable utmi vbuses */ + memset(tegra->xusb_utmi_vbus_regs, 0, + sizeof(tegra->xusb_utmi_vbus_regs)); + for (i = 0; i < XUSB_UTMI_COUNT; i++) { + struct regulator *reg = NULL; + const char *reg_name = supply->utmi_vbuses[i]; + if (BIT(XUSB_UTMI_INDEX + i) & tegra->bdata->portmap) { + if (i == 0 && tegra->transceiver) + continue; + reg = devm_regulator_get(&pdev->dev, reg_name); + if (IS_ERR(reg)) { dev_err(&pdev->dev, - "5p0v: regulator enable failed:%d\n", - err); - goto err_put_s3p3v_reg; + "%s regulator not found: %ld.", + reg_name, PTR_ERR(reg)); + err = PTR_ERR(reg); + } else { + err = regulator_enable(reg); + if (err < 0) { + dev_err(&pdev->dev, + "%s: regulator enable failed: %d\n", + reg_name, err); + } } + if (err) + goto err_put_utmi_vbus_reg; } + tegra->xusb_utmi_vbus_regs[i] = reg; } tegra->xusb_s1p8v_reg = @@ -1496,13 +1505,13 @@ static int tegra_xusb_regulator_init(struct tegra_xhci_hcd *tegra, dev_err(&pdev->dev, "1p8v regulator not found: %ld." , PTR_ERR(tegra->xusb_s1p8v_reg)); err = PTR_ERR(tegra->xusb_s1p8v_reg); - goto err_put_s5p0v_reg; + goto err_put_utmi_vbus_reg; } else { err = regulator_enable(tegra->xusb_s1p8v_reg); if (err < 0) { dev_err(&pdev->dev, "1p8v: regulator enable failed:%d\n", err); - goto err_put_s5p0v_reg; + goto err_put_utmi_vbus_reg; } } @@ -1522,60 +1531,20 @@ static int tegra_xusb_regulator_init(struct tegra_xhci_hcd *tegra, } } - if (tegra->bdata->uses_different_vbus_per_port) { - tegra->xusb_s5p0v1_reg = devm_regulator_get(&pdev->dev, - supply->s5p0v1); - if (IS_ERR(tegra->xusb_s5p0v1_reg)) { - dev_err(&pdev->dev, "5p0v1 regulator not found: %ld." - , PTR_ERR(tegra->xusb_s5p0v1_reg)); - err = PTR_ERR(tegra->xusb_s5p0v1_reg); - goto err_put_s1p05v_reg; - } else { - if (tegra->bdata->portmap & TEGRA_XUSB_USB2_P1) - err = regulator_enable(tegra->xusb_s5p0v1_reg); - if (err < 0) { - dev_err(&pdev->dev, - "5p0v1: regulator enable failed:%d\n", err); - goto err_put_s1p05v_reg; - } - } - - tegra->xusb_s5p0v2_reg = devm_regulator_get(&pdev->dev, - supply->s5p0v2); - if (IS_ERR(tegra->xusb_s5p0v2_reg)) { - dev_err(&pdev->dev, "5p0v2 regulator not found: %ld." - , PTR_ERR(tegra->xusb_s5p0v2_reg)); - err = PTR_ERR(tegra->xusb_s5p0v2_reg); - goto err_put_s1p5v1_reg; - } else { - if (tegra->bdata->portmap & TEGRA_XUSB_USB2_P2) - err = regulator_enable(tegra->xusb_s5p0v2_reg); - if (err < 0) { - dev_err(&pdev->dev, - "5p0v2: regulator enable failed:%d\n", err); - goto err_put_s1p5v1_reg; - } - } - } return err; -err_put_s1p5v1_reg: - if (tegra->bdata->uses_different_vbus_per_port && - tegra->bdata->portmap & TEGRA_XUSB_USB2_P1) - regulator_disable(tegra->xusb_s5p0v1_reg); -err_put_s1p05v_reg: - regulator_disable(tegra->xusb_s1p05v_reg); err_put_s1p8v_reg: regulator_disable(tegra->xusb_s1p8v_reg); -err_put_s5p0v_reg: - if ((tegra->bdata->portmap & TEGRA_XUSB_USB2_P0) && !tegra->transceiver) - regulator_disable(tegra->xusb_s5p0v_reg); -err_put_s3p3v_reg: +err_put_utmi_vbus_reg: + for (i = 0; i < XUSB_UTMI_COUNT; i++) { + struct regulator *reg = tegra->xusb_utmi_vbus_regs[i]; + if (!IS_ERR_OR_NULL(reg)) + regulator_disable(reg); + } regulator_disable(tegra->xusb_s3p3v_reg); err_null_regulator: - tegra->xusb_s5p0v_reg = NULL; - tegra->xusb_s5p0v1_reg = NULL; - tegra->xusb_s5p0v2_reg = NULL; + for (i = 0; i < XUSB_UTMI_COUNT; i++) + tegra->xusb_utmi_vbus_regs[i] = NULL; tegra->xusb_s1p05v_reg = NULL; tegra->xusb_s3p3v_reg = NULL; tegra->xusb_s1p8v_reg = NULL; @@ -1584,23 +1553,24 @@ err_null_regulator: static void tegra_xusb_regulator_deinit(struct tegra_xhci_hcd *tegra) { + int i; + regulator_disable(tegra->xusb_s1p05v_reg); regulator_disable(tegra->xusb_s1p8v_reg); - if ((tegra->bdata->portmap & TEGRA_XUSB_USB2_P0) && !tegra->transceiver) - regulator_disable(tegra->xusb_s5p0v_reg); - regulator_disable(tegra->xusb_s3p3v_reg); - if (tegra->bdata->uses_different_vbus_per_port) { - if (tegra->bdata->portmap & TEGRA_XUSB_USB2_P1) - regulator_disable(tegra->xusb_s5p0v1_reg); - if (tegra->bdata->portmap & TEGRA_XUSB_USB2_P2) - regulator_disable(tegra->xusb_s5p0v2_reg); + + for (i = 0; i < XUSB_UTMI_COUNT; i++) { + if (BIT(XUSB_UTMI_INDEX + i) & tegra->bdata->portmap) { + struct regulator *reg = tegra->xusb_utmi_vbus_regs[i]; + if (!IS_ERR_OR_NULL(reg)) + regulator_disable(reg); + tegra->xusb_utmi_vbus_regs[i] = NULL; + } } + regulator_disable(tegra->xusb_s3p3v_reg); + tegra->xusb_s1p05v_reg = NULL; tegra->xusb_s1p8v_reg = NULL; - tegra->xusb_s5p0v_reg = NULL; - tegra->xusb_s5p0v1_reg = NULL; - tegra->xusb_s5p0v2_reg = NULL; tegra->xusb_s3p3v_reg = NULL; } |