summaryrefslogtreecommitdiff
path: root/drivers/phy/broadcom/phy-brcm-usb-init-synopsys.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/phy/broadcom/phy-brcm-usb-init-synopsys.c')
-rw-r--r--drivers/phy/broadcom/phy-brcm-usb-init-synopsys.c77
1 files changed, 71 insertions, 6 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;
}