summaryrefslogtreecommitdiff
path: root/drivers/phy
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/phy')
-rw-r--r--drivers/phy/broadcom/phy-brcm-usb-init-synopsys.c77
-rw-r--r--drivers/phy/broadcom/phy-brcm-usb-init.c26
-rw-r--r--drivers/phy/broadcom/phy-brcm-usb-init.h11
-rw-r--r--drivers/phy/broadcom/phy-brcm-usb.c25
4 files changed, 105 insertions, 34 deletions
diff --git a/drivers/phy/broadcom/phy-brcm-usb-init-synopsys.c b/drivers/phy/broadcom/phy-brcm-usb-init-synopsys.c
index 60969827a67a..456dc4a100c2 100644
--- a/drivers/phy/broadcom/phy-brcm-usb-init-synopsys.c
+++ b/drivers/phy/broadcom/phy-brcm-usb-init-synopsys.c
@@ -26,7 +26,6 @@
#define PIARBCTL_MISC_CAM1_MEM_PAGE_MASK 0x00000f00
#define PIARBCTL_MISC_CAM0_MEM_PAGE_MASK 0x000000f0
#define PIARBCTL_MISC_SATA_PRIORITY_MASK 0x0000000f
-#define PIARBCTL_USB_M_ASB_CTRL 0x10
#define PIARBCTL_MISC_USB_ONLY_MASK \
(PIARBCTL_MISC_USB_SELECT_MASK | \
@@ -51,14 +50,27 @@
#define USB_CTRL_USB_PM_STATUS 0x08
#define USB_CTRL_USB_DEVICE_CTL1 0x10
#define USB_CTRL_USB_DEVICE_CTL1_PORT_MODE_MASK 0x00000003
+#define USB_CTRL_TEST_PORT_CTL 0x30
+#define USB_CTRL_TEST_PORT_CTL_TPOUT_SEL_MASK 0x000000ff
+#define USB_CTRL_TEST_PORT_CTL_TPOUT_SEL_PME_GEN_MASK 0x0000002e
+#define USB_CTRL_TP_DIAG1 0x34
+#define USB_CTLR_TP_DIAG1_wake_MASK 0x00000002
+#define USB_CTRL_CTLR_CSHCR 0x50
+#define USB_CTRL_CTLR_CSHCR_ctl_pme_en_MASK 0x00040000
/* Register definitions for the USB_PHY block in 7211b0 */
+#define USB_PHY_PLL_CTL 0x00
+#define USB_PHY_PLL_CTL_PLL_RESETB_MASK 0x40000000
#define USB_PHY_PLL_LDO_CTL 0x08
#define USB_PHY_PLL_LDO_CTL_AFE_CORERDY_MASK 0x00000004
+#define USB_PHY_PLL_LDO_CTL_AFE_LDO_PWRDWNB_MASK 0x00000002
+#define USB_PHY_PLL_LDO_CTL_AFE_BG_PWRDWNB_MASK 0x00000001
#define USB_PHY_UTMI_CTL_1 0x04
#define USB_PHY_UTMI_CTL_1_POWER_UP_FSM_EN_MASK 0x00000800
#define USB_PHY_UTMI_CTL_1_PHY_MODE_MASK 0x0000000c
#define USB_PHY_UTMI_CTL_1_PHY_MODE_SHIFT 2
+#define USB_PHY_IDDQ 0x1c
+#define USB_PHY_IDDQ_phy_iddq_MASK 0x00000001
#define USB_PHY_STATUS 0x20
#define USB_PHY_STATUS_pll_lock_MASK 0x00000001
@@ -199,6 +211,17 @@ static void usb_init_common(struct brcm_usb_init_params *params)
}
}
+static void usb_wake_enable_7211b0(struct brcm_usb_init_params *params,
+ bool enable)
+{
+ void __iomem *ctrl = params->regs[BRCM_REGS_CTRL];
+
+ if (enable)
+ USB_CTRL_SET(ctrl, CTLR_CSHCR, ctl_pme_en);
+ else
+ USB_CTRL_UNSET(ctrl, CTLR_CSHCR, ctl_pme_en);
+}
+
static void usb_init_common_7211b0(struct brcm_usb_init_params *params)
{
void __iomem *ctrl = params->regs[BRCM_REGS_CTRL];
@@ -210,9 +233,27 @@ static void usb_init_common_7211b0(struct brcm_usb_init_params *params)
if (params->syscon_piarbctl)
syscon_piarbctl_init(params->syscon_piarbctl);
+ USB_CTRL_UNSET(ctrl, USB_PM, USB_PWRDN);
+
+ usb_wake_enable_7211b0(params, false);
+ if (!params->wake_enabled) {
+
+ /* undo possible suspend settings */
+ brcm_usb_writel(0, usb_phy + USB_PHY_IDDQ);
+ reg = brcm_usb_readl(usb_phy + USB_PHY_PLL_CTL);
+ reg |= USB_PHY_PLL_CTL_PLL_RESETB_MASK;
+ brcm_usb_writel(reg, usb_phy + USB_PHY_PLL_CTL);
+
+ /* temporarily enable FSM so PHY comes up properly */
+ reg = brcm_usb_readl(usb_phy + USB_PHY_UTMI_CTL_1);
+ reg |= USB_PHY_UTMI_CTL_1_POWER_UP_FSM_EN_MASK;
+ brcm_usb_writel(reg, usb_phy + USB_PHY_UTMI_CTL_1);
+ }
+
/* Init the PHY */
- reg = brcm_usb_readl(usb_phy + USB_PHY_PLL_LDO_CTL);
- reg |= USB_PHY_PLL_LDO_CTL_AFE_CORERDY_MASK;
+ reg = USB_PHY_PLL_LDO_CTL_AFE_CORERDY_MASK |
+ USB_PHY_PLL_LDO_CTL_AFE_LDO_PWRDWNB_MASK |
+ USB_PHY_PLL_LDO_CTL_AFE_BG_PWRDWNB_MASK;
brcm_usb_writel(reg, usb_phy + USB_PHY_PLL_LDO_CTL);
/* wait for lock */
@@ -276,12 +317,36 @@ static void usb_uninit_common(struct brcm_usb_init_params *params)
}
+static void usb_uninit_common_7211b0(struct brcm_usb_init_params *params)
+{
+ void __iomem *ctrl = params->regs[BRCM_REGS_CTRL];
+ void __iomem *usb_phy = params->regs[BRCM_REGS_USB_PHY];
+ u32 reg;
+
+ pr_debug("%s\n", __func__);
+
+ if (params->wake_enabled) {
+ USB_CTRL_SET(ctrl, TEST_PORT_CTL, TPOUT_SEL_PME_GEN);
+ usb_wake_enable_7211b0(params, true);
+ } else {
+ USB_CTRL_SET(ctrl, USB_PM, USB_PWRDN);
+ brcm_usb_writel(0, usb_phy + USB_PHY_PLL_LDO_CTL);
+ reg = brcm_usb_readl(usb_phy + USB_PHY_PLL_CTL);
+ reg &= ~USB_PHY_PLL_CTL_PLL_RESETB_MASK;
+ brcm_usb_writel(reg, usb_phy + USB_PHY_PLL_CTL);
+ brcm_usb_writel(USB_PHY_IDDQ_phy_iddq_MASK,
+ usb_phy + USB_PHY_IDDQ);
+ }
+
+}
+
static void usb_uninit_xhci(struct brcm_usb_init_params *params)
{
pr_debug("%s\n", __func__);
- xhci_soft_reset(params, 1);
+ if (!params->wake_enabled)
+ xhci_soft_reset(params, 1);
}
static int usb_get_dual_select(struct brcm_usb_init_params *params)
@@ -309,7 +374,6 @@ static void usb_set_dual_select(struct brcm_usb_init_params *params, int mode)
brcm_usb_writel(reg, USB_CTRL_REG(ctrl, USB_DEVICE_CTL1));
}
-
static const struct brcm_usb_init_ops bcm7216_ops = {
.init_ipp = usb_init_ipp,
.init_common = usb_init_common,
@@ -324,7 +388,7 @@ static const struct brcm_usb_init_ops bcm7211b0_ops = {
.init_ipp = usb_init_ipp,
.init_common = usb_init_common_7211b0,
.init_xhci = usb_init_xhci,
- .uninit_common = usb_uninit_common,
+ .uninit_common = usb_uninit_common_7211b0,
.uninit_xhci = usb_uninit_xhci,
.get_dual_select = usb_get_dual_select,
.set_dual_select = usb_set_dual_select,
@@ -346,4 +410,5 @@ void brcm_usb_dvr_init_7211b0(struct brcm_usb_init_params *params)
params->family_name = "7211";
params->ops = &bcm7211b0_ops;
+ params->suspend_with_clocks = true;
}
diff --git a/drivers/phy/broadcom/phy-brcm-usb-init.c b/drivers/phy/broadcom/phy-brcm-usb-init.c
index 17acc3c1051b..9391ab42a12b 100644
--- a/drivers/phy/broadcom/phy-brcm-usb-init.c
+++ b/drivers/phy/broadcom/phy-brcm-usb-init.c
@@ -783,12 +783,24 @@ static void usb_init_ipp(struct brcm_usb_init_params *params)
msleep(50);
}
+static void usb_wake_enable(struct brcm_usb_init_params *params,
+ bool enable)
+{
+ void __iomem *ctrl = params->regs[BRCM_REGS_CTRL];
+
+ if (enable)
+ USB_CTRL_SET(ctrl, USB_PM, RMTWKUP_EN);
+ else
+ USB_CTRL_UNSET(ctrl, USB_PM, RMTWKUP_EN);
+}
+
static void usb_init_common(struct brcm_usb_init_params *params)
{
u32 reg;
void __iomem *ctrl = params->regs[BRCM_REGS_CTRL];
/* Clear any pending wake conditions */
+ usb_wake_enable(params, false);
reg = brcm_usb_readl(USB_CTRL_REG(ctrl, USB_PM_STATUS));
brcm_usb_writel(reg, USB_CTRL_REG(ctrl, USB_PM_STATUS));
@@ -935,6 +947,8 @@ static void usb_uninit_common(struct brcm_usb_init_params *params)
if (USB_CTRL_MASK_FAMILY(params, PLL_CTL, PLL_IDDQ_PWRDN))
USB_CTRL_SET_FAMILY(params, PLL_CTL, PLL_IDDQ_PWRDN);
+ if (params->wake_enabled)
+ usb_wake_enable(params, true);
}
static void usb_uninit_eohci(struct brcm_usb_init_params *params)
@@ -978,17 +992,6 @@ static void usb_set_dual_select(struct brcm_usb_init_params *params, int mode)
}
}
-static void usb_wake_enable(struct brcm_usb_init_params *params,
- int enable)
-{
- void __iomem *ctrl = params->regs[BRCM_REGS_CTRL];
-
- if (enable)
- USB_CTRL_SET(ctrl, USB_PM, RMTWKUP_EN);
- else
- USB_CTRL_UNSET(ctrl, USB_PM, RMTWKUP_EN);
-}
-
static const struct brcm_usb_init_ops bcm7445_ops = {
.init_ipp = usb_init_ipp,
.init_common = usb_init_common,
@@ -999,7 +1002,6 @@ static const struct brcm_usb_init_ops bcm7445_ops = {
.uninit_xhci = usb_uninit_xhci,
.get_dual_select = usb_get_dual_select,
.set_dual_select = usb_set_dual_select,
- .wake_enable = usb_wake_enable,
};
void brcm_usb_dvr_init_7445(struct brcm_usb_init_params *params)
diff --git a/drivers/phy/broadcom/phy-brcm-usb-init.h b/drivers/phy/broadcom/phy-brcm-usb-init.h
index 4cdd9cc1c5a3..899b9eb43fad 100644
--- a/drivers/phy/broadcom/phy-brcm-usb-init.h
+++ b/drivers/phy/broadcom/phy-brcm-usb-init.h
@@ -46,8 +46,6 @@ struct brcm_usb_init_ops {
void (*uninit_xhci)(struct brcm_usb_init_params *params);
int (*get_dual_select)(struct brcm_usb_init_params *params);
void (*set_dual_select)(struct brcm_usb_init_params *params, int mode);
- void (*wake_enable)(struct brcm_usb_init_params *params,
- int enable);
};
struct brcm_usb_init_params {
@@ -62,6 +60,8 @@ struct brcm_usb_init_params {
const u32 *usb_reg_bits_map;
const struct brcm_usb_init_ops *ops;
struct regmap *syscon_piarbctl;
+ bool wake_enabled;
+ bool suspend_with_clocks;
};
void brcm_usb_dvr_init_7445(struct brcm_usb_init_params *params);
@@ -145,13 +145,6 @@ static inline void brcm_usb_uninit_xhci(struct brcm_usb_init_params *ini)
ini->ops->uninit_xhci(ini);
}
-static inline void brcm_usb_wake_enable(struct brcm_usb_init_params *ini,
- int enable)
-{
- if (ini->ops->wake_enable)
- ini->ops->wake_enable(ini, enable);
-}
-
static inline int brcm_usb_get_dual_select(struct brcm_usb_init_params *ini)
{
if (ini->ops->get_dual_select)
diff --git a/drivers/phy/broadcom/phy-brcm-usb.c b/drivers/phy/broadcom/phy-brcm-usb.c
index 1ab44f54244b..491bbd46c5b3 100644
--- a/drivers/phy/broadcom/phy-brcm-usb.c
+++ b/drivers/phy/broadcom/phy-brcm-usb.c
@@ -535,16 +535,26 @@ static int brcm_usb_phy_suspend(struct device *dev)
struct brcm_usb_phy_data *priv = dev_get_drvdata(dev);
if (priv->init_count) {
+ priv->ini.wake_enabled = device_may_wakeup(dev);
if (priv->phys[BRCM_USB_PHY_3_0].inited)
brcm_usb_uninit_xhci(&priv->ini);
if (priv->phys[BRCM_USB_PHY_2_0].inited)
brcm_usb_uninit_eohci(&priv->ini);
brcm_usb_uninit_common(&priv->ini);
- brcm_usb_wake_enable(&priv->ini, true);
- if (priv->phys[BRCM_USB_PHY_3_0].inited)
- clk_disable_unprepare(priv->usb_30_clk);
- if (priv->phys[BRCM_USB_PHY_2_0].inited || !priv->has_eohci)
- clk_disable_unprepare(priv->usb_20_clk);
+
+ /*
+ * Handle the clocks unless needed for wake. This has
+ * to work for both older XHCI->3.0-clks, EOHCI->2.0-clks
+ * and newer XHCI->2.0-clks/3.0-clks.
+ */
+
+ if (!priv->ini.suspend_with_clocks) {
+ if (priv->phys[BRCM_USB_PHY_3_0].inited)
+ clk_disable_unprepare(priv->usb_30_clk);
+ if (priv->phys[BRCM_USB_PHY_2_0].inited ||
+ !priv->has_eohci)
+ clk_disable_unprepare(priv->usb_20_clk);
+ }
if (priv->wake_irq >= 0)
enable_irq_wake(priv->wake_irq);
}
@@ -557,7 +567,6 @@ static int brcm_usb_phy_resume(struct device *dev)
clk_prepare_enable(priv->usb_20_clk);
clk_prepare_enable(priv->usb_30_clk);
- brcm_usb_wake_enable(&priv->ini, false);
brcm_usb_init_ipp(&priv->ini);
/*
@@ -579,6 +588,8 @@ static int brcm_usb_phy_resume(struct device *dev)
} else if (priv->has_xhci) {
brcm_usb_uninit_xhci(&priv->ini);
clk_disable_unprepare(priv->usb_30_clk);
+ if (!priv->has_eohci)
+ clk_disable_unprepare(priv->usb_20_clk);
}
} else {
if (priv->has_xhci)
@@ -589,7 +600,7 @@ static int brcm_usb_phy_resume(struct device *dev)
clk_disable_unprepare(priv->usb_20_clk);
clk_disable_unprepare(priv->usb_30_clk);
}
-
+ priv->ini.wake_enabled = false;
return 0;
}
#endif /* CONFIG_PM_SLEEP */