diff options
Diffstat (limited to 'target/linux/bcm4908/patches-5.4/084-v5.6-0008-phy-usb-Add-support-for-new-Synopsys-USB-controller-.patch')
-rw-r--r-- | target/linux/bcm4908/patches-5.4/084-v5.6-0008-phy-usb-Add-support-for-new-Synopsys-USB-controller-.patch | 680 |
1 files changed, 680 insertions, 0 deletions
diff --git a/target/linux/bcm4908/patches-5.4/084-v5.6-0008-phy-usb-Add-support-for-new-Synopsys-USB-controller-.patch b/target/linux/bcm4908/patches-5.4/084-v5.6-0008-phy-usb-Add-support-for-new-Synopsys-USB-controller-.patch new file mode 100644 index 0000000000..008108c589 --- /dev/null +++ b/target/linux/bcm4908/patches-5.4/084-v5.6-0008-phy-usb-Add-support-for-new-Synopsys-USB-controller-.patch @@ -0,0 +1,680 @@ +From 9d5f51dcdb646c2ed21649d379fbb703994f1ec9 Mon Sep 17 00:00:00 2001 +From: Al Cooper <alcooperx@gmail.com> +Date: Fri, 3 Jan 2020 13:18:06 -0500 +Subject: [PATCH] phy: usb: Add support for new Synopsys USB controller on the + 7211b0 + +The 7211b0 has added the STB XHCI Synopsys controller and it +will be used instead of the RPi based DWC USB controller. The new +Synopsys XHCI controller core is the same one that is used on the +7216, but because of the way the STB USB PHY is used on both the A0 +and B0, some of the PHY control is different. + +Signed-off-by: Al Cooper <alcooperx@gmail.com> +Reviewed-by: Florian Fainelli <f.fainelli@gmail.com> +Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com> +--- + .../phy/broadcom/phy-brcm-usb-init-synopsys.c | 163 +++++++++++++++++- + drivers/phy/broadcom/phy-brcm-usb-init.c | 31 ++-- + drivers/phy/broadcom/phy-brcm-usb-init.h | 17 +- + drivers/phy/broadcom/phy-brcm-usb.c | 162 +++++++++++------ + 4 files changed, 295 insertions(+), 78 deletions(-) + +--- a/drivers/phy/broadcom/phy-brcm-usb-init-synopsys.c ++++ b/drivers/phy/broadcom/phy-brcm-usb-init-synopsys.c +@@ -12,10 +12,33 @@ + #include <linux/soc/brcmstb/brcmstb.h> + #include "phy-brcm-usb-init.h" + ++#define PHY_LOCK_TIMEOUT_MS 200 ++ ++/* Register definitions for syscon piarbctl registers */ ++#define PIARBCTL_CAM 0x00 ++#define PIARBCTL_SPLITTER 0x04 ++#define PIARBCTL_MISC 0x08 ++#define PIARBCTL_MISC_SECURE_MASK 0x80000000 ++#define PIARBCTL_MISC_USB_SELECT_MASK 0x40000000 ++#define PIARBCTL_MISC_USB_4G_SDRAM_MASK 0x20000000 ++#define PIARBCTL_MISC_USB_PRIORITY_MASK 0x000f0000 ++#define PIARBCTL_MISC_USB_MEM_PAGE_MASK 0x0000f000 ++#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 | \ ++ PIARBCTL_MISC_USB_4G_SDRAM_MASK | \ ++ PIARBCTL_MISC_USB_PRIORITY_MASK | \ ++ PIARBCTL_MISC_USB_MEM_PAGE_MASK) ++ + /* Register definitions for the USB CTRL block */ + #define USB_CTRL_SETUP 0x00 + #define USB_CTRL_SETUP_STRAP_IPP_SEL_MASK 0x02000000 + #define USB_CTRL_SETUP_SCB2_EN_MASK 0x00008000 ++#define USB_CTRL_SETUP_tca_drv_sel_MASK 0x01000000 + #define USB_CTRL_SETUP_SCB1_EN_MASK 0x00004000 + #define USB_CTRL_SETUP_SOFT_SHUTDOWN_MASK 0x00000200 + #define USB_CTRL_SETUP_IPP_MASK 0x00000020 +@@ -29,11 +52,73 @@ + #define USB_CTRL_USB_DEVICE_CTL1 0x10 + #define USB_CTRL_USB_DEVICE_CTL1_PORT_MODE_MASK 0x00000003 + ++/* Register definitions for the USB_PHY block in 7211b0 */ ++#define USB_PHY_PLL_LDO_CTL 0x08 ++#define USB_PHY_PLL_LDO_CTL_AFE_CORERDY_MASK 0x00000004 ++#define USB_PHY_UTMI_CTL_1 0x04 ++#define USB_PHY_UTMI_CTL_1_PHY_MODE_MASK 0x0000000c ++#define USB_PHY_UTMI_CTL_1_PHY_MODE_SHIFT 2 ++#define USB_PHY_STATUS 0x20 ++#define USB_PHY_STATUS_pll_lock_MASK 0x00000001 ++ ++/* Register definitions for the MDIO registers in the DWC2 block of ++ * the 7211b0. ++ * NOTE: The PHY's MDIO registers are only accessible through the ++ * legacy DesignWare USB controller even though it's not being used. ++ */ ++#define USB_GMDIOCSR 0 ++#define USB_GMDIOGEN 4 ++ ++ ++static void usb_mdio_write_7211b0(struct brcm_usb_init_params *params, ++ uint8_t addr, uint16_t data) ++{ ++ void __iomem *usb_mdio = params->regs[BRCM_REGS_USB_MDIO]; ++ ++ addr &= 0x1f; /* 5-bit address */ ++ brcm_usb_writel(0xffffffff, usb_mdio + USB_GMDIOGEN); ++ while (brcm_usb_readl(usb_mdio + USB_GMDIOCSR) & (1<<31)) ++ ; ++ brcm_usb_writel(0x59020000 | (addr << 18) | data, ++ usb_mdio + USB_GMDIOGEN); ++ while (brcm_usb_readl(usb_mdio + USB_GMDIOCSR) & (1<<31)) ++ ; ++ brcm_usb_writel(0x00000000, usb_mdio + USB_GMDIOGEN); ++ while (brcm_usb_readl(usb_mdio + USB_GMDIOCSR) & (1<<31)) ++ ; ++} ++ ++static uint16_t __maybe_unused usb_mdio_read_7211b0( ++ struct brcm_usb_init_params *params, uint8_t addr) ++{ ++ void __iomem *usb_mdio = params->regs[BRCM_REGS_USB_MDIO]; ++ ++ addr &= 0x1f; /* 5-bit address */ ++ brcm_usb_writel(0xffffffff, usb_mdio + USB_GMDIOGEN); ++ while (brcm_usb_readl(usb_mdio + USB_GMDIOCSR) & (1<<31)) ++ ; ++ brcm_usb_writel(0x69020000 | (addr << 18), usb_mdio + USB_GMDIOGEN); ++ while (brcm_usb_readl(usb_mdio + USB_GMDIOCSR) & (1<<31)) ++ ; ++ brcm_usb_writel(0x00000000, usb_mdio + USB_GMDIOGEN); ++ while (brcm_usb_readl(usb_mdio + USB_GMDIOCSR) & (1<<31)) ++ ; ++ return brcm_usb_readl(usb_mdio + USB_GMDIOCSR) & 0xffff; ++} ++ ++static void usb2_eye_fix_7211b0(struct brcm_usb_init_params *params) ++{ ++ /* select bank */ ++ usb_mdio_write_7211b0(params, 0x1f, 0x80a0); ++ ++ /* Set the eye */ ++ usb_mdio_write_7211b0(params, 0x0a, 0xc6a0); ++} + + static void xhci_soft_reset(struct brcm_usb_init_params *params, + int on_off) + { +- void __iomem *ctrl = params->ctrl_regs; ++ void __iomem *ctrl = params->regs[BRCM_REGS_CTRL]; + + /* Assert reset */ + if (on_off) +@@ -45,7 +130,7 @@ static void xhci_soft_reset(struct brcm_ + + static void usb_init_ipp(struct brcm_usb_init_params *params) + { +- void __iomem *ctrl = params->ctrl_regs; ++ void __iomem *ctrl = params->regs[BRCM_REGS_CTRL]; + u32 reg; + u32 orig_reg; + +@@ -72,10 +157,18 @@ static void usb_init_ipp(struct brcm_usb + msleep(50); + } + ++static void syscon_piarbctl_init(struct regmap *rmap) ++{ ++ /* Switch from legacy USB OTG controller to new STB USB controller */ ++ regmap_update_bits(rmap, PIARBCTL_MISC, PIARBCTL_MISC_USB_ONLY_MASK, ++ PIARBCTL_MISC_USB_SELECT_MASK | ++ PIARBCTL_MISC_USB_4G_SDRAM_MASK); ++} ++ + static void usb_init_common(struct brcm_usb_init_params *params) + { + u32 reg; +- void __iomem *ctrl = params->ctrl_regs; ++ void __iomem *ctrl = params->regs[BRCM_REGS_CTRL]; + + pr_debug("%s\n", __func__); + +@@ -100,6 +193,45 @@ static void usb_init_common(struct brcm_ + } + } + ++static void usb_init_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]; ++ int timeout_ms = PHY_LOCK_TIMEOUT_MS; ++ u32 reg; ++ ++ if (params->syscon_piarbctl) ++ syscon_piarbctl_init(params->syscon_piarbctl); ++ ++ /* Init the PHY */ ++ reg = brcm_usb_readl(usb_phy + USB_PHY_PLL_LDO_CTL); ++ reg |= USB_PHY_PLL_LDO_CTL_AFE_CORERDY_MASK; ++ brcm_usb_writel(reg, usb_phy + USB_PHY_PLL_LDO_CTL); ++ ++ /* wait for lock */ ++ while (timeout_ms-- > 0) { ++ reg = brcm_usb_readl(usb_phy + USB_PHY_STATUS); ++ if (reg & USB_PHY_STATUS_pll_lock_MASK) ++ break; ++ usleep_range(1000, 2000); ++ } ++ ++ /* Set the PHY_MODE */ ++ reg = brcm_usb_readl(usb_phy + USB_PHY_UTMI_CTL_1); ++ reg &= ~USB_PHY_UTMI_CTL_1_PHY_MODE_MASK; ++ reg |= params->mode << USB_PHY_UTMI_CTL_1_PHY_MODE_SHIFT; ++ brcm_usb_writel(reg, usb_phy + USB_PHY_UTMI_CTL_1); ++ ++ /* Fix the incorrect default */ ++ reg = brcm_usb_readl(ctrl + USB_CTRL_SETUP); ++ reg &= ~USB_CTRL_SETUP_tca_drv_sel_MASK; ++ brcm_usb_writel(reg, ctrl + USB_CTRL_SETUP); ++ ++ usb_init_common(params); ++ ++ usb2_eye_fix_7211b0(params); ++} ++ + static void usb_init_xhci(struct brcm_usb_init_params *params) + { + pr_debug("%s\n", __func__); +@@ -109,7 +241,7 @@ static void usb_init_xhci(struct brcm_us + + static void usb_uninit_common(struct brcm_usb_init_params *params) + { +- void __iomem *ctrl = params->ctrl_regs; ++ void __iomem *ctrl = params->regs[BRCM_REGS_CTRL]; + + pr_debug("%s\n", __func__); + +@@ -127,7 +259,7 @@ static void usb_uninit_xhci(struct brcm_ + + static int usb_get_dual_select(struct brcm_usb_init_params *params) + { +- void __iomem *ctrl = params->ctrl_regs; ++ void __iomem *ctrl = params->regs[BRCM_REGS_CTRL]; + u32 reg = 0; + + pr_debug("%s\n", __func__); +@@ -139,7 +271,7 @@ static int usb_get_dual_select(struct br + + static void usb_set_dual_select(struct brcm_usb_init_params *params, int mode) + { +- void __iomem *ctrl = params->ctrl_regs; ++ void __iomem *ctrl = params->regs[BRCM_REGS_CTRL]; + u32 reg; + + pr_debug("%s\n", __func__); +@@ -161,6 +293,16 @@ static const struct brcm_usb_init_ops bc + .set_dual_select = usb_set_dual_select, + }; + ++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_xhci = usb_uninit_xhci, ++ .get_dual_select = usb_get_dual_select, ++ .set_dual_select = usb_set_dual_select, ++}; ++ + void brcm_usb_dvr_init_7216(struct brcm_usb_init_params *params) + { + +@@ -169,3 +311,12 @@ void brcm_usb_dvr_init_7216(struct brcm_ + params->family_name = "7216"; + params->ops = &bcm7216_ops; + } ++ ++void brcm_usb_dvr_init_7211b0(struct brcm_usb_init_params *params) ++{ ++ ++ pr_debug("%s\n", __func__); ++ ++ params->family_name = "7211"; ++ params->ops = &bcm7211b0_ops; ++} +--- a/drivers/phy/broadcom/phy-brcm-usb-init.c ++++ b/drivers/phy/broadcom/phy-brcm-usb-init.c +@@ -401,7 +401,7 @@ void usb_ctrl_unset_family(struct brcm_u + u32 mask; + + mask = params->usb_reg_bits_map[field]; +- brcm_usb_ctrl_unset(params->ctrl_regs + reg_offset, mask); ++ brcm_usb_ctrl_unset(params->regs[BRCM_REGS_CTRL] + reg_offset, mask); + }; + + static inline +@@ -411,7 +411,7 @@ void usb_ctrl_set_family(struct brcm_usb + u32 mask; + + mask = params->usb_reg_bits_map[field]; +- brcm_usb_ctrl_set(params->ctrl_regs + reg_offset, mask); ++ brcm_usb_ctrl_set(params->regs[BRCM_REGS_CTRL] + reg_offset, mask); + }; + + static u32 brcmusb_usb_mdio_read(void __iomem *ctrl_base, u32 reg, int mode) +@@ -544,7 +544,7 @@ static void brcmusb_usb3_pll_54mhz(struc + { + u32 ofs; + int ii; +- void __iomem *ctrl_base = params->ctrl_regs; ++ void __iomem *ctrl_base = params->regs[BRCM_REGS_CTRL]; + + /* + * On newer B53 based SoC's, the reference clock for the +@@ -625,7 +625,7 @@ static void brcmusb_usb3_ssc_enable(void + + static void brcmusb_usb3_phy_workarounds(struct brcm_usb_init_params *params) + { +- void __iomem *ctrl_base = params->ctrl_regs; ++ void __iomem *ctrl_base = params->regs[BRCM_REGS_CTRL]; + + brcmusb_usb3_pll_fix(ctrl_base); + brcmusb_usb3_pll_54mhz(params); +@@ -667,7 +667,7 @@ static void brcmusb_memc_fix(struct brcm + + static void brcmusb_usb3_otp_fix(struct brcm_usb_init_params *params) + { +- void __iomem *xhci_ec_base = params->xhci_ec_regs; ++ void __iomem *xhci_ec_base = params->regs[BRCM_REGS_XHCI_EC]; + u32 val; + + if (params->family_id != 0x74371000 || !xhci_ec_base) +@@ -680,8 +680,8 @@ static void brcmusb_usb3_otp_fix(struct + brcm_usb_writel(val, USB_XHCI_EC_REG(xhci_ec_base, IRADAT)); + + /* Reset USB 3.0 PHY for workaround to take effect */ +- USB_CTRL_UNSET(params->ctrl_regs, USB30_CTL1, PHY3_RESETB); +- USB_CTRL_SET(params->ctrl_regs, USB30_CTL1, PHY3_RESETB); ++ USB_CTRL_UNSET(params->regs[BRCM_REGS_CTRL], USB30_CTL1, PHY3_RESETB); ++ USB_CTRL_SET(params->regs[BRCM_REGS_CTRL], USB30_CTL1, PHY3_RESETB); + } + + static void brcmusb_xhci_soft_reset(struct brcm_usb_init_params *params, +@@ -740,7 +740,7 @@ static enum brcm_family_type get_family_ + + static void usb_init_ipp(struct brcm_usb_init_params *params) + { +- void __iomem *ctrl = params->ctrl_regs; ++ void __iomem *ctrl = params->regs[BRCM_REGS_CTRL]; + u32 reg; + u32 orig_reg; + +@@ -786,7 +786,7 @@ static void usb_init_ipp(struct brcm_usb + static void usb_init_common(struct brcm_usb_init_params *params) + { + u32 reg; +- void __iomem *ctrl = params->ctrl_regs; ++ void __iomem *ctrl = params->regs[BRCM_REGS_CTRL]; + + /* Clear any pending wake conditions */ + reg = brcm_usb_readl(USB_CTRL_REG(ctrl, USB_PM_STATUS)); +@@ -866,7 +866,7 @@ static void usb_init_common(struct brcm_ + static void usb_init_eohci(struct brcm_usb_init_params *params) + { + u32 reg; +- void __iomem *ctrl = params->ctrl_regs; ++ void __iomem *ctrl = params->regs[BRCM_REGS_CTRL]; + + if (USB_CTRL_MASK_FAMILY(params, USB_PM, USB20_HC_RESETB)) + USB_CTRL_SET_FAMILY(params, USB_PM, USB20_HC_RESETB); +@@ -902,7 +902,7 @@ static void usb_init_eohci(struct brcm_u + + static void usb_init_xhci(struct brcm_usb_init_params *params) + { +- void __iomem *ctrl = params->ctrl_regs; ++ void __iomem *ctrl = params->regs[BRCM_REGS_CTRL]; + + USB_CTRL_UNSET(ctrl, USB30_PCTL, PHY3_IDDQ_OVERRIDE); + /* 1 millisecond - for USB clocks to settle down */ +@@ -944,12 +944,13 @@ static void usb_uninit_eohci(struct brcm + static void usb_uninit_xhci(struct brcm_usb_init_params *params) + { + brcmusb_xhci_soft_reset(params, 1); +- USB_CTRL_SET(params->ctrl_regs, USB30_PCTL, PHY3_IDDQ_OVERRIDE); ++ USB_CTRL_SET(params->regs[BRCM_REGS_CTRL], USB30_PCTL, ++ PHY3_IDDQ_OVERRIDE); + } + + static int usb_get_dual_select(struct brcm_usb_init_params *params) + { +- void __iomem *ctrl = params->ctrl_regs; ++ void __iomem *ctrl = params->regs[BRCM_REGS_CTRL]; + u32 reg = 0; + + pr_debug("%s\n", __func__); +@@ -963,7 +964,7 @@ static int usb_get_dual_select(struct br + + static void usb_set_dual_select(struct brcm_usb_init_params *params, int mode) + { +- void __iomem *ctrl = params->ctrl_regs; ++ void __iomem *ctrl = params->regs[BRCM_REGS_CTRL]; + u32 reg; + + pr_debug("%s\n", __func__); +@@ -980,7 +981,7 @@ 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->ctrl_regs; ++ void __iomem *ctrl = params->regs[BRCM_REGS_CTRL]; + + if (enable) + USB_CTRL_SET(ctrl, USB_PM, RMTWKUP_EN); +--- a/drivers/phy/broadcom/phy-brcm-usb-init.h ++++ b/drivers/phy/broadcom/phy-brcm-usb-init.h +@@ -6,12 +6,21 @@ + #ifndef _USB_BRCM_COMMON_INIT_H + #define _USB_BRCM_COMMON_INIT_H + ++#include <linux/regmap.h> ++ + #define USB_CTLR_MODE_HOST 0 + #define USB_CTLR_MODE_DEVICE 1 + #define USB_CTLR_MODE_DRD 2 + #define USB_CTLR_MODE_TYPEC_PD 3 + +-struct brcm_usb_init_params; ++enum brcmusb_reg_sel { ++ BRCM_REGS_CTRL = 0, ++ BRCM_REGS_XHCI_EC, ++ BRCM_REGS_XHCI_GBL, ++ BRCM_REGS_USB_PHY, ++ BRCM_REGS_USB_MDIO, ++ BRCM_REGS_MAX ++}; + + #define USB_CTRL_REG(base, reg) ((void __iomem *)base + USB_CTRL_##reg) + #define USB_XHCI_EC_REG(base, reg) ((void __iomem *)base + USB_XHCI_EC_##reg) +@@ -41,9 +50,7 @@ struct brcm_usb_init_ops { + }; + + struct brcm_usb_init_params { +- void __iomem *ctrl_regs; +- void __iomem *xhci_ec_regs; +- void __iomem *xhci_gbl_regs; ++ void __iomem *regs[BRCM_REGS_MAX]; + int ioc; + int ipp; + int mode; +@@ -53,10 +60,12 @@ struct brcm_usb_init_params { + const char *family_name; + const u32 *usb_reg_bits_map; + const struct brcm_usb_init_ops *ops; ++ struct regmap *syscon_piarbctl; + }; + + void brcm_usb_dvr_init_7445(struct brcm_usb_init_params *params); + void brcm_usb_dvr_init_7216(struct brcm_usb_init_params *params); ++void brcm_usb_dvr_init_7211b0(struct brcm_usb_init_params *params); + + static inline u32 brcm_usb_readl(void __iomem *addr) + { +--- a/drivers/phy/broadcom/phy-brcm-usb.c ++++ b/drivers/phy/broadcom/phy-brcm-usb.c +@@ -16,6 +16,7 @@ + #include <linux/interrupt.h> + #include <linux/soc/brcmstb/brcmstb.h> + #include <dt-bindings/phy/phy.h> ++#include <linux/mfd/syscon.h> + + #include "phy-brcm-usb-init.h" + +@@ -32,6 +33,11 @@ struct value_to_name_map { + const char *name; + }; + ++struct match_chip_info { ++ void *init_func; ++ u8 required_regs[BRCM_REGS_MAX + 1]; ++}; ++ + static struct value_to_name_map brcm_dr_mode_to_name[] = { + { USB_CTLR_MODE_HOST, "host" }, + { USB_CTLR_MODE_DEVICE, "peripheral" }, +@@ -64,6 +70,10 @@ struct brcm_usb_phy_data { + struct brcm_usb_phy phys[BRCM_USB_PHY_ID_MAX]; + }; + ++static s8 *node_reg_names[BRCM_REGS_MAX] = { ++ "crtl", "xhci_ec", "xhci_gbl", "usb_phy", "usb_mdio" ++}; ++ + static irqreturn_t brcm_usb_phy_wake_isr(int irq, void *dev_id) + { + struct phy *gphy = dev_id; +@@ -241,15 +251,86 @@ static const struct attribute_group brcm + .attrs = brcm_usb_phy_attrs, + }; + ++static struct match_chip_info chip_info_7216 = { ++ .init_func = &brcm_usb_dvr_init_7216, ++ .required_regs = { ++ BRCM_REGS_CTRL, ++ BRCM_REGS_XHCI_EC, ++ BRCM_REGS_XHCI_GBL, ++ -1, ++ }, ++}; ++ ++static struct match_chip_info chip_info_7211b0 = { ++ .init_func = &brcm_usb_dvr_init_7211b0, ++ .required_regs = { ++ BRCM_REGS_CTRL, ++ BRCM_REGS_XHCI_EC, ++ BRCM_REGS_XHCI_GBL, ++ BRCM_REGS_USB_PHY, ++ BRCM_REGS_USB_MDIO, ++ -1, ++ }, ++}; ++ ++static struct match_chip_info chip_info_7445 = { ++ .init_func = &brcm_usb_dvr_init_7445, ++ .required_regs = { ++ BRCM_REGS_CTRL, ++ BRCM_REGS_XHCI_EC, ++ -1, ++ }, ++}; ++ + static const struct of_device_id brcm_usb_dt_ids[] = { + { + .compatible = "brcm,bcm7216-usb-phy", +- .data = &brcm_usb_dvr_init_7216, ++ .data = &chip_info_7216, ++ }, ++ { ++ .compatible = "brcm,bcm7211-usb-phy", ++ .data = &chip_info_7211b0, ++ }, ++ { ++ .compatible = "brcm,brcmstb-usb-phy", ++ .data = &chip_info_7445, + }, +- { .compatible = "brcm,brcmstb-usb-phy" }, + { /* sentinel */ } + }; + ++static int brcm_usb_get_regs(struct platform_device *pdev, ++ enum brcmusb_reg_sel regs, ++ struct brcm_usb_init_params *ini) ++{ ++ struct resource *res; ++ ++ /* Older DT nodes have ctrl and optional xhci_ec by index only */ ++ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, ++ node_reg_names[regs]); ++ if (res == NULL) { ++ if (regs == BRCM_REGS_CTRL) { ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ } else if (regs == BRCM_REGS_XHCI_EC) { ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 1); ++ /* XHCI_EC registers are optional */ ++ if (res == NULL) ++ return 0; ++ } ++ if (res == NULL) { ++ dev_err(&pdev->dev, "can't get %s base address\n", ++ node_reg_names[regs]); ++ return 1; ++ } ++ } ++ ini->regs[regs] = devm_ioremap_resource(&pdev->dev, res); ++ if (IS_ERR(ini->regs[regs])) { ++ dev_err(&pdev->dev, "can't map %s register space\n", ++ node_reg_names[regs]); ++ return 1; ++ } ++ return 0; ++} ++ + static int brcm_usb_phy_dvr_init(struct platform_device *pdev, + struct brcm_usb_phy_data *priv, + struct device_node *dn) +@@ -325,9 +406,6 @@ static int brcm_usb_phy_dvr_init(struct + + static int brcm_usb_phy_probe(struct platform_device *pdev) + { +- struct resource *res_ctrl; +- struct resource *res_xhciec = NULL; +- struct resource *res_xhcigbl = NULL; + struct device *dev = &pdev->dev; + struct brcm_usb_phy_data *priv; + struct phy_provider *phy_provider; +@@ -335,6 +413,10 @@ static int brcm_usb_phy_probe(struct pla + int err; + const char *mode; + const struct of_device_id *match; ++ void (*dvr_init)(struct brcm_usb_init_params *params); ++ const struct match_chip_info *info; ++ struct regmap *rmap; ++ int x; + + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); + if (!priv) +@@ -345,58 +427,13 @@ static int brcm_usb_phy_probe(struct pla + priv->ini.product_id = brcmstb_get_product_id(); + + match = of_match_node(brcm_usb_dt_ids, dev->of_node); +- if (match && match->data) { +- void (*dvr_init)(struct brcm_usb_init_params *params); +- +- dvr_init = match->data; +- (*dvr_init)(&priv->ini); +- } else { +- brcm_usb_dvr_init_7445(&priv->ini); +- } ++ info = match->data; ++ dvr_init = info->init_func; ++ (*dvr_init)(&priv->ini); + + dev_dbg(dev, "Best mapping table is for %s\n", + priv->ini.family_name); + +- /* Newer DT node has reg-names. xhci_ec and xhci_gbl are optional. */ +- res_ctrl = platform_get_resource_byname(pdev, IORESOURCE_MEM, "ctrl"); +- if (res_ctrl != NULL) { +- res_xhciec = platform_get_resource_byname(pdev, +- IORESOURCE_MEM, +- "xhci_ec"); +- res_xhcigbl = platform_get_resource_byname(pdev, +- IORESOURCE_MEM, +- "xhci_gbl"); +- } else { +- /* Older DT node without reg-names, use index */ +- res_ctrl = platform_get_resource(pdev, IORESOURCE_MEM, 0); +- if (res_ctrl == NULL) { +- dev_err(dev, "can't get CTRL base address\n"); +- return -EINVAL; +- } +- res_xhciec = platform_get_resource(pdev, IORESOURCE_MEM, 1); +- } +- priv->ini.ctrl_regs = devm_ioremap_resource(dev, res_ctrl); +- if (IS_ERR(priv->ini.ctrl_regs)) { +- dev_err(dev, "can't map CTRL register space\n"); +- return -EINVAL; +- } +- if (res_xhciec) { +- priv->ini.xhci_ec_regs = +- devm_ioremap_resource(dev, res_xhciec); +- if (IS_ERR(priv->ini.xhci_ec_regs)) { +- dev_err(dev, "can't map XHCI EC register space\n"); +- return -EINVAL; +- } +- } +- if (res_xhcigbl) { +- priv->ini.xhci_gbl_regs = +- devm_ioremap_resource(dev, res_xhcigbl); +- if (IS_ERR(priv->ini.xhci_gbl_regs)) { +- dev_err(dev, "can't map XHCI Global register space\n"); +- return -EINVAL; +- } +- } +- + of_property_read_u32(dn, "brcm,ipp", &priv->ini.ipp); + of_property_read_u32(dn, "brcm,ioc", &priv->ini.ioc); + +@@ -412,6 +449,16 @@ static int brcm_usb_phy_probe(struct pla + if (of_property_read_bool(dn, "brcm,has-eohci")) + priv->has_eohci = true; + ++ for (x = 0; x < BRCM_REGS_MAX; x++) { ++ if (info->required_regs[x] >= BRCM_REGS_MAX) ++ break; ++ ++ err = brcm_usb_get_regs(pdev, info->required_regs[x], ++ &priv->ini); ++ if (err) ++ return -EINVAL; ++ } ++ + err = brcm_usb_phy_dvr_init(pdev, priv, dn); + if (err) + return err; +@@ -431,6 +478,15 @@ static int brcm_usb_phy_probe(struct pla + if (err) + dev_warn(dev, "Error creating sysfs attributes\n"); + ++ /* Get piarbctl syscon if it exists */ ++ rmap = syscon_regmap_lookup_by_phandle(dev->of_node, ++ "syscon-piarbctl"); ++ if (IS_ERR(rmap)) ++ rmap = syscon_regmap_lookup_by_phandle(dev->of_node, ++ "brcm,syscon-piarbctl"); ++ if (!IS_ERR(rmap)) ++ priv->ini.syscon_piarbctl = rmap; ++ + /* start with everything off */ + if (priv->has_xhci) + brcm_usb_uninit_xhci(&priv->ini); |