lkml.org 
[lkml]   [2020]   [Nov]   [19]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH v5 05/16] phy: tegra: xusb: Rearrange UPHY init on Tegra210
    Date
    This commit is a preparation for enabling XUSB SC7 support.
    It rearranges Tegra210 XUSB PADCTL UPHY initialization sequence,
    for the following reasons:

    1. PLLE hardware power sequencer has to be enabled only after both
    PEX UPHY PLL and SATA UPHY PLL are initialized.
    tegra210_uphy_init() -> tegra210_pex_uphy_enable()
    -> tegra210_sata_uphy_enable()
    -> tegra210_plle_hw_sequence_start()
    -> tegra210_aux_mux_lp0_clamp_disable()

    2. At cold boot and SC7 exit, the following bits must be cleared after
    PEX/SATA lanes are out of IDDQ (IDDQ_DISABLE=1).
    a. XUSB_PADCTL_ELPG_PROGRAM1_AUX_MUX_LP0_CLAMP_EN,
    b. XUSB_PADCTL_ELPG_PROGRAM1_AUX_MUX_LP0_CLAMP_EN_EARLY
    c. XUSB_PADCTL_ELPG_PROGRAM1_AUX_MUX_LP0_VCORE_DOWN

    tegra210_pex_uphy_enable() and tegra210_sata_uphy_enable() are in
    charge of bringing lanes out of IDDQ, and then AUX_MUX_LP0_* bits
    will be cleared by tegra210_aux_mux_lp0_clamp_disable().

    Signed-off-by: JC Kuo <jckuo@nvidia.com>
    Acked-by: Thierry Reding <treding@nvidia.com>
    ---
    v5:
    no change
    v4:
    no change
    v3:
    make separate changes
    use "unsigned int" instead "int" type for PHY index
    add blank line for better readability

    drivers/phy/tegra/xusb-tegra210.c | 195 ++++++++++++++++--------------
    drivers/phy/tegra/xusb.h | 4 +-
    2 files changed, 103 insertions(+), 96 deletions(-)

    diff --git a/drivers/phy/tegra/xusb-tegra210.c b/drivers/phy/tegra/xusb-tegra210.c
    index 9bfecdfecf35..faacb866cd1f 100644
    --- a/drivers/phy/tegra/xusb-tegra210.c
    +++ b/drivers/phy/tegra/xusb-tegra210.c
    @@ -288,17 +288,19 @@ static int tegra210_pex_uphy_enable(struct tegra_xusb_padctl *padctl)
    struct tegra_xusb_pcie_pad *pcie = to_pcie_pad(padctl->pcie);
    unsigned long timeout;
    u32 value;
    + unsigned int i;
    int err;

    - if (pcie->enable > 0) {
    - pcie->enable++;
    + if (pcie->enable)
    return 0;
    - }

    err = clk_prepare_enable(pcie->pll);
    if (err < 0)
    return err;

    + if (tegra210_plle_hw_sequence_is_enabled())
    + goto skip_pll_init;
    +
    err = reset_control_deassert(pcie->rst);
    if (err < 0)
    goto disable;
    @@ -481,7 +483,14 @@ static int tegra210_pex_uphy_enable(struct tegra_xusb_padctl *padctl)

    tegra210_xusb_pll_hw_sequence_start();

    - pcie->enable++;
    +skip_pll_init:
    + pcie->enable = true;
    +
    + for (i = 0; i < padctl->pcie->soc->num_lanes; i++) {
    + value = padctl_readl(padctl, XUSB_PADCTL_USB3_PAD_MUX);
    + value |= XUSB_PADCTL_USB3_PAD_MUX_PCIE_IDDQ_DISABLE(i);
    + padctl_writel(padctl, value, XUSB_PADCTL_USB3_PAD_MUX);
    + }

    return 0;

    @@ -495,28 +504,44 @@ static int tegra210_pex_uphy_enable(struct tegra_xusb_padctl *padctl)
    static void tegra210_pex_uphy_disable(struct tegra_xusb_padctl *padctl)
    {
    struct tegra_xusb_pcie_pad *pcie = to_pcie_pad(padctl->pcie);
    + u32 value;
    + unsigned int i;

    - if (WARN_ON(pcie->enable == 0))
    + if (WARN_ON(!pcie->enable))
    return;

    - if (--pcie->enable > 0)
    - return;
    + pcie->enable = false;
    +
    + for (i = 0; i < padctl->pcie->soc->num_lanes; i++) {
    + value = padctl_readl(padctl, XUSB_PADCTL_USB3_PAD_MUX);
    + value &= ~XUSB_PADCTL_USB3_PAD_MUX_PCIE_IDDQ_DISABLE(i);
    + padctl_writel(padctl, value, XUSB_PADCTL_USB3_PAD_MUX);
    + }

    clk_disable_unprepare(pcie->pll);
    }

    /* must be called under padctl->lock */
    -static int tegra210_sata_uphy_enable(struct tegra_xusb_padctl *padctl, bool usb)
    +static int tegra210_sata_uphy_enable(struct tegra_xusb_padctl *padctl)
    {
    struct tegra_xusb_sata_pad *sata = to_sata_pad(padctl->sata);
    + struct tegra_xusb_lane *lane = tegra_xusb_find_lane(padctl, "sata", 0);
    unsigned long timeout;
    u32 value;
    + unsigned int i;
    int err;
    + bool usb;

    - if (sata->enable > 0) {
    - sata->enable++;
    + if (sata->enable)
    return 0;
    - }
    +
    + if (IS_ERR(lane))
    + return 0;
    +
    + if (tegra210_plle_hw_sequence_is_enabled())
    + goto skip_pll_init;
    +
    + usb = tegra_xusb_lane_check(lane, "usb3-ss");

    err = clk_prepare_enable(sata->pll);
    if (err < 0)
    @@ -717,7 +742,14 @@ static int tegra210_sata_uphy_enable(struct tegra_xusb_padctl *padctl, bool usb)

    tegra210_sata_pll_hw_sequence_start();

    - sata->enable++;
    +skip_pll_init:
    + sata->enable = true;
    +
    + for (i = 0; i < padctl->sata->soc->num_lanes; i++) {
    + value = padctl_readl(padctl, XUSB_PADCTL_USB3_PAD_MUX);
    + value |= XUSB_PADCTL_USB3_PAD_MUX_SATA_IDDQ_DISABLE(i);
    + padctl_writel(padctl, value, XUSB_PADCTL_USB3_PAD_MUX);
    + }

    return 0;

    @@ -731,25 +763,27 @@ static int tegra210_sata_uphy_enable(struct tegra_xusb_padctl *padctl, bool usb)
    static void tegra210_sata_uphy_disable(struct tegra_xusb_padctl *padctl)
    {
    struct tegra_xusb_sata_pad *sata = to_sata_pad(padctl->sata);
    + u32 value;
    + unsigned int i;

    - if (WARN_ON(sata->enable == 0))
    + if (WARN_ON(!sata->enable))
    return;

    - if (--sata->enable > 0)
    - return;
    + sata->enable = false;
    +
    + for (i = 0; i < padctl->sata->soc->num_lanes; i++) {
    + value = padctl_readl(padctl, XUSB_PADCTL_USB3_PAD_MUX);
    + value &= ~XUSB_PADCTL_USB3_PAD_MUX_SATA_IDDQ_DISABLE(i);
    + padctl_writel(padctl, value, XUSB_PADCTL_USB3_PAD_MUX);
    + }

    clk_disable_unprepare(sata->pll);
    }

    -static int tegra210_xusb_padctl_enable(struct tegra_xusb_padctl *padctl)
    +static void tegra210_aux_mux_lp0_clamp_disable(struct tegra_xusb_padctl *padctl)
    {
    u32 value;

    - mutex_lock(&padctl->lock);
    -
    - if (padctl->enable++ > 0)
    - goto out;
    -
    value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM1);
    value &= ~XUSB_PADCTL_ELPG_PROGRAM1_AUX_MUX_LP0_CLAMP_EN;
    padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM1);
    @@ -765,24 +799,12 @@ static int tegra210_xusb_padctl_enable(struct tegra_xusb_padctl *padctl)
    value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM1);
    value &= ~XUSB_PADCTL_ELPG_PROGRAM1_AUX_MUX_LP0_VCORE_DOWN;
    padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM1);
    -
    -out:
    - mutex_unlock(&padctl->lock);
    - return 0;
    }

    -static int tegra210_xusb_padctl_disable(struct tegra_xusb_padctl *padctl)
    +static void tegra210_aux_mux_lp0_clamp_enable(struct tegra_xusb_padctl *padctl)
    {
    u32 value;

    - mutex_lock(&padctl->lock);
    -
    - if (WARN_ON(padctl->enable == 0))
    - goto out;
    -
    - if (--padctl->enable > 0)
    - goto out;
    -
    value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM1);
    value |= XUSB_PADCTL_ELPG_PROGRAM1_AUX_MUX_LP0_VCORE_DOWN;
    padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM1);
    @@ -798,12 +820,38 @@ static int tegra210_xusb_padctl_disable(struct tegra_xusb_padctl *padctl)
    value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM1);
    value |= XUSB_PADCTL_ELPG_PROGRAM1_AUX_MUX_LP0_CLAMP_EN;
    padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM1);
    +}
    +
    +static int tegra210_uphy_init(struct tegra_xusb_padctl *padctl)
    +{
    + if (padctl->pcie)
    + tegra210_pex_uphy_enable(padctl);
    +
    + if (padctl->sata)
    + tegra210_sata_uphy_enable(padctl);
    +
    + if (!tegra210_plle_hw_sequence_is_enabled())
    + tegra210_plle_hw_sequence_start();
    + else
    + dev_dbg(padctl->dev, "PLLE is already in HW control\n");
    +
    + tegra210_aux_mux_lp0_clamp_disable(padctl);

    -out:
    - mutex_unlock(&padctl->lock);
    return 0;
    }

    +static void __maybe_unused
    +tegra210_uphy_deinit(struct tegra_xusb_padctl *padctl)
    +{
    + tegra210_aux_mux_lp0_clamp_enable(padctl);
    +
    + if (padctl->sata)
    + tegra210_sata_uphy_disable(padctl);
    +
    + if (padctl->pcie)
    + tegra210_pex_uphy_disable(padctl);
    +}
    +
    static int tegra210_hsic_set_idle(struct tegra_xusb_padctl *padctl,
    unsigned int index, bool idle)
    {
    @@ -940,14 +988,12 @@ static int tegra210_usb2_phy_init(struct phy *phy)
    XUSB_PADCTL_USB2_PAD_MUX_USB2_BIAS_PAD_SHIFT;
    padctl_writel(padctl, value, XUSB_PADCTL_USB2_PAD_MUX);

    - return tegra210_xusb_padctl_enable(padctl);
    + return 0;
    }

    static int tegra210_usb2_phy_exit(struct phy *phy)
    {
    - struct tegra_xusb_lane *lane = phy_get_drvdata(phy);
    -
    - return tegra210_xusb_padctl_disable(lane->pad->padctl);
    + return 0;
    }

    static int tegra210_xusb_padctl_vbus_override(struct tegra_xusb_padctl *padctl,
    @@ -1405,14 +1451,12 @@ static int tegra210_hsic_phy_init(struct phy *phy)
    XUSB_PADCTL_USB2_PAD_MUX_HSIC_PAD_TRK_SHIFT;
    padctl_writel(padctl, value, XUSB_PADCTL_USB2_PAD_MUX);

    - return tegra210_xusb_padctl_enable(padctl);
    + return 0;
    }

    static int tegra210_hsic_phy_exit(struct phy *phy)
    {
    - struct tegra_xusb_lane *lane = phy_get_drvdata(phy);
    -
    - return tegra210_xusb_padctl_disable(lane->pad->padctl);
    + return 0;
    }

    static int tegra210_hsic_phy_power_on(struct phy *phy)
    @@ -1776,38 +1820,28 @@ static const struct tegra_xusb_lane_ops tegra210_pcie_lane_ops = {
    static int tegra210_pcie_phy_init(struct phy *phy)
    {
    struct tegra_xusb_lane *lane = phy_get_drvdata(phy);
    + struct tegra_xusb_padctl *padctl = lane->pad->padctl;

    - return tegra210_xusb_padctl_enable(lane->pad->padctl);
    -}
    + mutex_lock(&padctl->lock);

    -static int tegra210_pcie_phy_exit(struct phy *phy)
    -{
    - struct tegra_xusb_lane *lane = phy_get_drvdata(phy);
    + tegra210_uphy_init(padctl);

    - return tegra210_xusb_padctl_disable(lane->pad->padctl);
    + mutex_unlock(&padctl->lock);
    +
    + return 0;
    }

    static int tegra210_pcie_phy_power_on(struct phy *phy)
    {
    struct tegra_xusb_lane *lane = phy_get_drvdata(phy);
    struct tegra_xusb_padctl *padctl = lane->pad->padctl;
    - u32 value;
    - int err;
    + int err = 0;

    mutex_lock(&padctl->lock);

    - err = tegra210_pex_uphy_enable(padctl);
    - if (err < 0)
    - goto unlock;
    -
    - value = padctl_readl(padctl, XUSB_PADCTL_USB3_PAD_MUX);
    - value |= XUSB_PADCTL_USB3_PAD_MUX_PCIE_IDDQ_DISABLE(lane->index);
    - padctl_writel(padctl, value, XUSB_PADCTL_USB3_PAD_MUX);
    -
    if (tegra_xusb_lane_check(lane, "usb3-ss"))
    err = tegra210_usb3_phy_power_on(phy);

    -unlock:
    mutex_unlock(&padctl->lock);
    return err;
    }
    @@ -1817,16 +1851,9 @@ static int tegra210_pcie_phy_power_off(struct phy *phy)
    struct tegra_xusb_lane *lane = phy_get_drvdata(phy);
    struct tegra_xusb_padctl *padctl = lane->pad->padctl;
    int err = 0;
    - u32 value;

    mutex_lock(&padctl->lock);

    - value = padctl_readl(padctl, XUSB_PADCTL_USB3_PAD_MUX);
    - value &= ~XUSB_PADCTL_USB3_PAD_MUX_PCIE_IDDQ_DISABLE(lane->index);
    - padctl_writel(padctl, value, XUSB_PADCTL_USB3_PAD_MUX);
    -
    - tegra210_pex_uphy_disable(padctl);
    -
    if (tegra_xusb_lane_check(lane, "usb3-ss"))
    err = tegra210_usb3_phy_power_off(phy);

    @@ -1836,7 +1863,6 @@ static int tegra210_pcie_phy_power_off(struct phy *phy)

    static const struct phy_ops tegra210_pcie_phy_ops = {
    .init = tegra210_pcie_phy_init,
    - .exit = tegra210_pcie_phy_exit,
    .power_on = tegra210_pcie_phy_power_on,
    .power_off = tegra210_pcie_phy_power_off,
    .owner = THIS_MODULE,
    @@ -1957,38 +1983,27 @@ static const struct tegra_xusb_lane_ops tegra210_sata_lane_ops = {
    static int tegra210_sata_phy_init(struct phy *phy)
    {
    struct tegra_xusb_lane *lane = phy_get_drvdata(phy);
    + struct tegra_xusb_padctl *padctl = lane->pad->padctl;

    - return tegra210_xusb_padctl_enable(lane->pad->padctl);
    -}
    + mutex_lock(&padctl->lock);

    -static int tegra210_sata_phy_exit(struct phy *phy)
    -{
    - struct tegra_xusb_lane *lane = phy_get_drvdata(phy);
    + tegra210_uphy_init(padctl);

    - return tegra210_xusb_padctl_disable(lane->pad->padctl);
    + mutex_unlock(&padctl->lock);
    + return 0;
    }

    static int tegra210_sata_phy_power_on(struct phy *phy)
    {
    struct tegra_xusb_lane *lane = phy_get_drvdata(phy);
    struct tegra_xusb_padctl *padctl = lane->pad->padctl;
    - u32 value;
    - int err;
    + int err = 0;

    mutex_lock(&padctl->lock);

    - err = tegra210_sata_uphy_enable(padctl, false);
    - if (err < 0)
    - goto unlock;
    -
    - value = padctl_readl(padctl, XUSB_PADCTL_USB3_PAD_MUX);
    - value |= XUSB_PADCTL_USB3_PAD_MUX_SATA_IDDQ_DISABLE(lane->index);
    - padctl_writel(padctl, value, XUSB_PADCTL_USB3_PAD_MUX);
    -
    if (tegra_xusb_lane_check(lane, "usb3-ss"))
    err = tegra210_usb3_phy_power_on(phy);

    -unlock:
    mutex_unlock(&padctl->lock);
    return err;
    }
    @@ -1998,16 +2013,9 @@ static int tegra210_sata_phy_power_off(struct phy *phy)
    struct tegra_xusb_lane *lane = phy_get_drvdata(phy);
    struct tegra_xusb_padctl *padctl = lane->pad->padctl;
    int err = 0;
    - u32 value;

    mutex_lock(&padctl->lock);

    - value = padctl_readl(padctl, XUSB_PADCTL_USB3_PAD_MUX);
    - value &= ~XUSB_PADCTL_USB3_PAD_MUX_SATA_IDDQ_DISABLE(lane->index);
    - padctl_writel(padctl, value, XUSB_PADCTL_USB3_PAD_MUX);
    -
    - tegra210_sata_uphy_disable(lane->pad->padctl);
    -
    if (tegra_xusb_lane_check(lane, "usb3-ss"))
    err = tegra210_usb3_phy_power_off(phy);

    @@ -2017,7 +2025,6 @@ static int tegra210_sata_phy_power_off(struct phy *phy)

    static const struct phy_ops tegra210_sata_phy_ops = {
    .init = tegra210_sata_phy_init,
    - .exit = tegra210_sata_phy_exit,
    .power_on = tegra210_sata_phy_power_on,
    .power_off = tegra210_sata_phy_power_off,
    .owner = THIS_MODULE,
    diff --git a/drivers/phy/tegra/xusb.h b/drivers/phy/tegra/xusb.h
    index 37a5550a84ac..ccb5dc9b1220 100644
    --- a/drivers/phy/tegra/xusb.h
    +++ b/drivers/phy/tegra/xusb.h
    @@ -232,7 +232,7 @@ struct tegra_xusb_pcie_pad {
    struct reset_control *rst;
    struct clk *pll;

    - unsigned int enable;
    + bool enable;
    };

    static inline struct tegra_xusb_pcie_pad *
    @@ -247,7 +247,7 @@ struct tegra_xusb_sata_pad {
    struct reset_control *rst;
    struct clk *pll;

    - unsigned int enable;
    + bool enable;
    };

    static inline struct tegra_xusb_sata_pad *
    --
    2.25.1
    \
     
     \ /
      Last update: 2020-11-19 09:58    [W:3.573 / U:0.580 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site