From 6c90999e2e0dee6e5e0322b89e8e6fb6f76aecc9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= Date: Thu, 14 Jan 2021 12:13:49 +0100 Subject: bcm4908: backport brcmstb USB PHY driver changes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This includes BCM4908 support Signed-off-by: Rafał Miłecki --- ...-support-for-wake-and-USB-low-power-mode-.patch | 328 +++++++++++++++++++++ 1 file changed, 328 insertions(+) create mode 100644 target/linux/bcm4908/patches-5.4/084-v5.6-0013-phy-usb-Add-support-for-wake-and-USB-low-power-mode-.patch (limited to 'target/linux/bcm4908/patches-5.4/084-v5.6-0013-phy-usb-Add-support-for-wake-and-USB-low-power-mode-.patch') diff --git a/target/linux/bcm4908/patches-5.4/084-v5.6-0013-phy-usb-Add-support-for-wake-and-USB-low-power-mode-.patch b/target/linux/bcm4908/patches-5.4/084-v5.6-0013-phy-usb-Add-support-for-wake-and-USB-low-power-mode-.patch new file mode 100644 index 0000000000..5a3a687adb --- /dev/null +++ b/target/linux/bcm4908/patches-5.4/084-v5.6-0013-phy-usb-Add-support-for-wake-and-USB-low-power-mode-.patch @@ -0,0 +1,328 @@ +From b0c0b66c0b432d3f3a1ae5849298ba9c7f1810c5 Mon Sep 17 00:00:00 2001 +From: Al Cooper +Date: Fri, 3 Jan 2020 13:18:11 -0500 +Subject: [PATCH] phy: usb: Add support for wake and USB low power mode for + 7211 S2/S5 + +Add support for 7211 USB wake. Disable all possible 7211 USB logic +for S2/S5 if USB wake is not enabled. + +On the 7211, the XHCI wake signal was not connected properly and +only goes to the USB1_USB1_CTRL_TP_DIAG1 diagonstic register. +The workaround is to have VPU code running that polls for the +proper bit in the DIAG register and to wake the system when +the bit is asserted. + +Signed-off-by: Al Cooper +Reviewed-by: Florian Fainelli +Signed-off-by: Kishon Vijay Abraham I +--- + .../phy/broadcom/phy-brcm-usb-init-synopsys.c | 77 +++++++++++++++++-- + drivers/phy/broadcom/phy-brcm-usb-init.c | 26 ++++--- + drivers/phy/broadcom/phy-brcm-usb-init.h | 11 +-- + drivers/phy/broadcom/phy-brcm-usb.c | 25 ++++-- + 4 files changed, 105 insertions(+), 34 deletions(-) + +--- 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_ + } + } + ++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(struc + 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 brc + + } + ++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 b + 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 bc + .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 brc + + params->family_name = "7211"; + params->ops = &bcm7211b0_ops; ++ params->suspend_with_clocks = true; + } +--- 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 + 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 brc + + 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 b + } + } + +-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 bc + .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) +--- 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( + 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) +--- 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 d + 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 de + + 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 de + } 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 de + 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 */ -- cgit v1.2.3