xref: /openbmc/linux/drivers/phy/broadcom/phy-brcm-usb-init-synopsys.c (revision bed63b636fedf47dbab899a5193ec5ec4539f6fc)
14e5b9c9aSAl Cooper // SPDX-License-Identifier: GPL-2.0
24e5b9c9aSAl Cooper /* Copyright (c) 2018, Broadcom */
34e5b9c9aSAl Cooper 
44e5b9c9aSAl Cooper /*
54e5b9c9aSAl Cooper  * This module contains USB PHY initialization for power up and S3 resume
64e5b9c9aSAl Cooper  * for newer Synopsys based USB hardware first used on the bcm7216.
74e5b9c9aSAl Cooper  */
84e5b9c9aSAl Cooper 
94e5b9c9aSAl Cooper #include <linux/delay.h>
104e5b9c9aSAl Cooper #include <linux/io.h>
114e5b9c9aSAl Cooper 
124e5b9c9aSAl Cooper #include <linux/soc/brcmstb/brcmstb.h>
134e5b9c9aSAl Cooper #include "phy-brcm-usb-init.h"
144e5b9c9aSAl Cooper 
159d5f51dcSAl Cooper #define PHY_LOCK_TIMEOUT_MS 200
169d5f51dcSAl Cooper 
179d5f51dcSAl Cooper /* Register definitions for syscon piarbctl registers */
189d5f51dcSAl Cooper #define PIARBCTL_CAM			0x00
199d5f51dcSAl Cooper #define PIARBCTL_SPLITTER		0x04
209d5f51dcSAl Cooper #define PIARBCTL_MISC			0x08
219d5f51dcSAl Cooper #define   PIARBCTL_MISC_SECURE_MASK			0x80000000
229d5f51dcSAl Cooper #define   PIARBCTL_MISC_USB_SELECT_MASK			0x40000000
239d5f51dcSAl Cooper #define   PIARBCTL_MISC_USB_4G_SDRAM_MASK		0x20000000
249d5f51dcSAl Cooper #define   PIARBCTL_MISC_USB_PRIORITY_MASK		0x000f0000
259d5f51dcSAl Cooper #define   PIARBCTL_MISC_USB_MEM_PAGE_MASK		0x0000f000
269d5f51dcSAl Cooper #define   PIARBCTL_MISC_CAM1_MEM_PAGE_MASK		0x00000f00
279d5f51dcSAl Cooper #define   PIARBCTL_MISC_CAM0_MEM_PAGE_MASK		0x000000f0
289d5f51dcSAl Cooper #define   PIARBCTL_MISC_SATA_PRIORITY_MASK		0x0000000f
299d5f51dcSAl Cooper #define PIARBCTL_USB_M_ASB_CTRL		0x10
309d5f51dcSAl Cooper 
319d5f51dcSAl Cooper #define PIARBCTL_MISC_USB_ONLY_MASK		\
329d5f51dcSAl Cooper 	(PIARBCTL_MISC_USB_SELECT_MASK |	\
339d5f51dcSAl Cooper 	 PIARBCTL_MISC_USB_4G_SDRAM_MASK |	\
349d5f51dcSAl Cooper 	 PIARBCTL_MISC_USB_PRIORITY_MASK |	\
359d5f51dcSAl Cooper 	 PIARBCTL_MISC_USB_MEM_PAGE_MASK)
369d5f51dcSAl Cooper 
374e5b9c9aSAl Cooper /* Register definitions for the USB CTRL block */
384e5b9c9aSAl Cooper #define USB_CTRL_SETUP			0x00
394e5b9c9aSAl Cooper #define   USB_CTRL_SETUP_STRAP_IPP_SEL_MASK		0x02000000
404e5b9c9aSAl Cooper #define   USB_CTRL_SETUP_SCB2_EN_MASK			0x00008000
419d5f51dcSAl Cooper #define   USB_CTRL_SETUP_tca_drv_sel_MASK		0x01000000
424e5b9c9aSAl Cooper #define   USB_CTRL_SETUP_SCB1_EN_MASK			0x00004000
434e5b9c9aSAl Cooper #define   USB_CTRL_SETUP_SOFT_SHUTDOWN_MASK		0x00000200
444e5b9c9aSAl Cooper #define   USB_CTRL_SETUP_IPP_MASK			0x00000020
454e5b9c9aSAl Cooper #define   USB_CTRL_SETUP_IOC_MASK			0x00000010
464e5b9c9aSAl Cooper #define USB_CTRL_USB_PM			0x04
474e5b9c9aSAl Cooper #define   USB_CTRL_USB_PM_USB_PWRDN_MASK		0x80000000
484e5b9c9aSAl Cooper #define   USB_CTRL_USB_PM_SOFT_RESET_MASK		0x40000000
494e5b9c9aSAl Cooper #define   USB_CTRL_USB_PM_BDC_SOFT_RESETB_MASK		0x00800000
504e5b9c9aSAl Cooper #define   USB_CTRL_USB_PM_XHC_SOFT_RESETB_MASK		0x00400000
514e5b9c9aSAl Cooper #define USB_CTRL_USB_PM_STATUS		0x08
524e5b9c9aSAl Cooper #define USB_CTRL_USB_DEVICE_CTL1	0x10
534e5b9c9aSAl Cooper #define   USB_CTRL_USB_DEVICE_CTL1_PORT_MODE_MASK	0x00000003
544e5b9c9aSAl Cooper 
559d5f51dcSAl Cooper /* Register definitions for the USB_PHY block in 7211b0 */
569d5f51dcSAl Cooper #define USB_PHY_PLL_LDO_CTL		0x08
579d5f51dcSAl Cooper #define   USB_PHY_PLL_LDO_CTL_AFE_CORERDY_MASK		0x00000004
589d5f51dcSAl Cooper #define USB_PHY_UTMI_CTL_1		0x04
59fc430aeaSAl Cooper #define   USB_PHY_UTMI_CTL_1_POWER_UP_FSM_EN_MASK	0x00000800
609d5f51dcSAl Cooper #define   USB_PHY_UTMI_CTL_1_PHY_MODE_MASK		0x0000000c
619d5f51dcSAl Cooper #define   USB_PHY_UTMI_CTL_1_PHY_MODE_SHIFT		2
629d5f51dcSAl Cooper #define USB_PHY_STATUS			0x20
639d5f51dcSAl Cooper #define   USB_PHY_STATUS_pll_lock_MASK			0x00000001
649d5f51dcSAl Cooper 
659d5f51dcSAl Cooper /* Register definitions for the MDIO registers in the DWC2 block of
669d5f51dcSAl Cooper  * the 7211b0.
679d5f51dcSAl Cooper  * NOTE: The PHY's MDIO registers are only accessible through the
689d5f51dcSAl Cooper  * legacy DesignWare USB controller even though it's not being used.
699d5f51dcSAl Cooper  */
709d5f51dcSAl Cooper #define USB_GMDIOCSR	0
719d5f51dcSAl Cooper #define USB_GMDIOGEN	4
729d5f51dcSAl Cooper 
73*bed63b63SAl Cooper /* Register definitions for the BDC EC block in 7211b0 */
74*bed63b63SAl Cooper #define BDC_EC_AXIRDA			0x0c
75*bed63b63SAl Cooper #define   BDC_EC_AXIRDA_RTS_MASK			0xf0000000
76*bed63b63SAl Cooper #define   BDC_EC_AXIRDA_RTS_SHIFT			28
77*bed63b63SAl Cooper 
789d5f51dcSAl Cooper 
799d5f51dcSAl Cooper static void usb_mdio_write_7211b0(struct brcm_usb_init_params *params,
809d5f51dcSAl Cooper 				  uint8_t addr, uint16_t data)
819d5f51dcSAl Cooper {
829d5f51dcSAl Cooper 	void __iomem *usb_mdio = params->regs[BRCM_REGS_USB_MDIO];
839d5f51dcSAl Cooper 
849d5f51dcSAl Cooper 	addr &= 0x1f; /* 5-bit address */
859d5f51dcSAl Cooper 	brcm_usb_writel(0xffffffff, usb_mdio + USB_GMDIOGEN);
869d5f51dcSAl Cooper 	while (brcm_usb_readl(usb_mdio + USB_GMDIOCSR) & (1<<31))
879d5f51dcSAl Cooper 		;
889d5f51dcSAl Cooper 	brcm_usb_writel(0x59020000 | (addr << 18) | data,
899d5f51dcSAl Cooper 			usb_mdio + USB_GMDIOGEN);
909d5f51dcSAl Cooper 	while (brcm_usb_readl(usb_mdio + USB_GMDIOCSR) & (1<<31))
919d5f51dcSAl Cooper 		;
929d5f51dcSAl Cooper 	brcm_usb_writel(0x00000000, usb_mdio + USB_GMDIOGEN);
939d5f51dcSAl Cooper 	while (brcm_usb_readl(usb_mdio + USB_GMDIOCSR) & (1<<31))
949d5f51dcSAl Cooper 		;
959d5f51dcSAl Cooper }
969d5f51dcSAl Cooper 
979d5f51dcSAl Cooper static uint16_t __maybe_unused usb_mdio_read_7211b0(
989d5f51dcSAl Cooper 	struct brcm_usb_init_params *params, uint8_t addr)
999d5f51dcSAl Cooper {
1009d5f51dcSAl Cooper 	void __iomem *usb_mdio = params->regs[BRCM_REGS_USB_MDIO];
1019d5f51dcSAl Cooper 
1029d5f51dcSAl Cooper 	addr &= 0x1f; /* 5-bit address */
1039d5f51dcSAl Cooper 	brcm_usb_writel(0xffffffff, usb_mdio + USB_GMDIOGEN);
1049d5f51dcSAl Cooper 	while (brcm_usb_readl(usb_mdio + USB_GMDIOCSR) & (1<<31))
1059d5f51dcSAl Cooper 		;
1069d5f51dcSAl Cooper 	brcm_usb_writel(0x69020000 | (addr << 18), usb_mdio + USB_GMDIOGEN);
1079d5f51dcSAl Cooper 	while (brcm_usb_readl(usb_mdio + USB_GMDIOCSR) & (1<<31))
1089d5f51dcSAl Cooper 		;
1099d5f51dcSAl Cooper 	brcm_usb_writel(0x00000000, usb_mdio + USB_GMDIOGEN);
1109d5f51dcSAl Cooper 	while (brcm_usb_readl(usb_mdio + USB_GMDIOCSR) & (1<<31))
1119d5f51dcSAl Cooper 		;
1129d5f51dcSAl Cooper 	return brcm_usb_readl(usb_mdio + USB_GMDIOCSR) & 0xffff;
1139d5f51dcSAl Cooper }
1149d5f51dcSAl Cooper 
1159d5f51dcSAl Cooper static void usb2_eye_fix_7211b0(struct brcm_usb_init_params *params)
1169d5f51dcSAl Cooper {
1179d5f51dcSAl Cooper 	/* select bank */
1189d5f51dcSAl Cooper 	usb_mdio_write_7211b0(params, 0x1f, 0x80a0);
1199d5f51dcSAl Cooper 
1209d5f51dcSAl Cooper 	/* Set the eye */
1219d5f51dcSAl Cooper 	usb_mdio_write_7211b0(params, 0x0a, 0xc6a0);
1229d5f51dcSAl Cooper }
1234e5b9c9aSAl Cooper 
1244e5b9c9aSAl Cooper static void xhci_soft_reset(struct brcm_usb_init_params *params,
1254e5b9c9aSAl Cooper 			int on_off)
1264e5b9c9aSAl Cooper {
1279d5f51dcSAl Cooper 	void __iomem *ctrl = params->regs[BRCM_REGS_CTRL];
1284e5b9c9aSAl Cooper 
1294e5b9c9aSAl Cooper 	/* Assert reset */
1304e5b9c9aSAl Cooper 	if (on_off)
1314e5b9c9aSAl Cooper 		USB_CTRL_UNSET(ctrl, USB_PM, XHC_SOFT_RESETB);
1324e5b9c9aSAl Cooper 	/* De-assert reset */
1334e5b9c9aSAl Cooper 	else
1344e5b9c9aSAl Cooper 		USB_CTRL_SET(ctrl, USB_PM, XHC_SOFT_RESETB);
1354e5b9c9aSAl Cooper }
1364e5b9c9aSAl Cooper 
1374e5b9c9aSAl Cooper static void usb_init_ipp(struct brcm_usb_init_params *params)
1384e5b9c9aSAl Cooper {
1399d5f51dcSAl Cooper 	void __iomem *ctrl = params->regs[BRCM_REGS_CTRL];
1404e5b9c9aSAl Cooper 	u32 reg;
1414e5b9c9aSAl Cooper 	u32 orig_reg;
1424e5b9c9aSAl Cooper 
1434e5b9c9aSAl Cooper 	pr_debug("%s\n", __func__);
1444e5b9c9aSAl Cooper 
1454e5b9c9aSAl Cooper 	orig_reg = reg = brcm_usb_readl(USB_CTRL_REG(ctrl, SETUP));
1464e5b9c9aSAl Cooper 	if (params->ipp != 2)
1474e5b9c9aSAl Cooper 		/* override ipp strap pin (if it exits) */
1484e5b9c9aSAl Cooper 		reg &= ~(USB_CTRL_MASK(SETUP, STRAP_IPP_SEL));
1494e5b9c9aSAl Cooper 
1504e5b9c9aSAl Cooper 	/* Override the default OC and PP polarity */
1514e5b9c9aSAl Cooper 	reg &= ~(USB_CTRL_MASK(SETUP, IPP) | USB_CTRL_MASK(SETUP, IOC));
1524e5b9c9aSAl Cooper 	if (params->ioc)
1534e5b9c9aSAl Cooper 		reg |= USB_CTRL_MASK(SETUP, IOC);
1544e5b9c9aSAl Cooper 	if (params->ipp == 1)
1554e5b9c9aSAl Cooper 		reg |= USB_CTRL_MASK(SETUP, IPP);
1564e5b9c9aSAl Cooper 	brcm_usb_writel(reg, USB_CTRL_REG(ctrl, SETUP));
1574e5b9c9aSAl Cooper 
1584e5b9c9aSAl Cooper 	/*
1594e5b9c9aSAl Cooper 	 * If we're changing IPP, make sure power is off long enough
1604e5b9c9aSAl Cooper 	 * to turn off any connected devices.
1614e5b9c9aSAl Cooper 	 */
1624e5b9c9aSAl Cooper 	if ((reg ^ orig_reg) & USB_CTRL_MASK(SETUP, IPP))
1634e5b9c9aSAl Cooper 		msleep(50);
1644e5b9c9aSAl Cooper }
1654e5b9c9aSAl Cooper 
1669d5f51dcSAl Cooper static void syscon_piarbctl_init(struct regmap *rmap)
1679d5f51dcSAl Cooper {
1689d5f51dcSAl Cooper 	/* Switch from legacy USB OTG controller to new STB USB controller */
1699d5f51dcSAl Cooper 	regmap_update_bits(rmap, PIARBCTL_MISC, PIARBCTL_MISC_USB_ONLY_MASK,
1709d5f51dcSAl Cooper 			   PIARBCTL_MISC_USB_SELECT_MASK |
1719d5f51dcSAl Cooper 			   PIARBCTL_MISC_USB_4G_SDRAM_MASK);
1729d5f51dcSAl Cooper }
1739d5f51dcSAl Cooper 
1744e5b9c9aSAl Cooper static void usb_init_common(struct brcm_usb_init_params *params)
1754e5b9c9aSAl Cooper {
1764e5b9c9aSAl Cooper 	u32 reg;
1779d5f51dcSAl Cooper 	void __iomem *ctrl = params->regs[BRCM_REGS_CTRL];
1784e5b9c9aSAl Cooper 
1794e5b9c9aSAl Cooper 	pr_debug("%s\n", __func__);
1804e5b9c9aSAl Cooper 
1814e5b9c9aSAl Cooper 	USB_CTRL_UNSET(ctrl, USB_PM, USB_PWRDN);
1824e5b9c9aSAl Cooper 	/* 1 millisecond - for USB clocks to settle down */
1834e5b9c9aSAl Cooper 	usleep_range(1000, 2000);
1844e5b9c9aSAl Cooper 
1854e5b9c9aSAl Cooper 	if (USB_CTRL_MASK(USB_DEVICE_CTL1, PORT_MODE)) {
1864e5b9c9aSAl Cooper 		reg = brcm_usb_readl(USB_CTRL_REG(ctrl, USB_DEVICE_CTL1));
1874e5b9c9aSAl Cooper 		reg &= ~USB_CTRL_MASK(USB_DEVICE_CTL1, PORT_MODE);
1884e5b9c9aSAl Cooper 		reg |= params->mode;
1894e5b9c9aSAl Cooper 		brcm_usb_writel(reg, USB_CTRL_REG(ctrl, USB_DEVICE_CTL1));
1904e5b9c9aSAl Cooper 	}
1914e5b9c9aSAl Cooper 	switch (params->mode) {
1924e5b9c9aSAl Cooper 	case USB_CTLR_MODE_HOST:
1934e5b9c9aSAl Cooper 		USB_CTRL_UNSET(ctrl, USB_PM, BDC_SOFT_RESETB);
1944e5b9c9aSAl Cooper 		break;
1954e5b9c9aSAl Cooper 	default:
1964e5b9c9aSAl Cooper 		USB_CTRL_UNSET(ctrl, USB_PM, BDC_SOFT_RESETB);
1974e5b9c9aSAl Cooper 		USB_CTRL_SET(ctrl, USB_PM, BDC_SOFT_RESETB);
1984e5b9c9aSAl Cooper 		break;
1994e5b9c9aSAl Cooper 	}
2004e5b9c9aSAl Cooper }
2014e5b9c9aSAl Cooper 
2029d5f51dcSAl Cooper static void usb_init_common_7211b0(struct brcm_usb_init_params *params)
2039d5f51dcSAl Cooper {
2049d5f51dcSAl Cooper 	void __iomem *ctrl = params->regs[BRCM_REGS_CTRL];
2059d5f51dcSAl Cooper 	void __iomem *usb_phy = params->regs[BRCM_REGS_USB_PHY];
206*bed63b63SAl Cooper 	void __iomem *bdc_ec = params->regs[BRCM_REGS_BDC_EC];
2079d5f51dcSAl Cooper 	int timeout_ms = PHY_LOCK_TIMEOUT_MS;
2089d5f51dcSAl Cooper 	u32 reg;
2099d5f51dcSAl Cooper 
2109d5f51dcSAl Cooper 	if (params->syscon_piarbctl)
2119d5f51dcSAl Cooper 		syscon_piarbctl_init(params->syscon_piarbctl);
2129d5f51dcSAl Cooper 
2139d5f51dcSAl Cooper 	/* Init the PHY */
2149d5f51dcSAl Cooper 	reg = brcm_usb_readl(usb_phy + USB_PHY_PLL_LDO_CTL);
2159d5f51dcSAl Cooper 	reg |= USB_PHY_PLL_LDO_CTL_AFE_CORERDY_MASK;
2169d5f51dcSAl Cooper 	brcm_usb_writel(reg, usb_phy + USB_PHY_PLL_LDO_CTL);
2179d5f51dcSAl Cooper 
2189d5f51dcSAl Cooper 	/* wait for lock */
2199d5f51dcSAl Cooper 	while (timeout_ms-- > 0) {
2209d5f51dcSAl Cooper 		reg = brcm_usb_readl(usb_phy + USB_PHY_STATUS);
2219d5f51dcSAl Cooper 		if (reg & USB_PHY_STATUS_pll_lock_MASK)
2229d5f51dcSAl Cooper 			break;
2239d5f51dcSAl Cooper 		usleep_range(1000, 2000);
2249d5f51dcSAl Cooper 	}
2259d5f51dcSAl Cooper 
2269d5f51dcSAl Cooper 	/* Set the PHY_MODE */
2279d5f51dcSAl Cooper 	reg = brcm_usb_readl(usb_phy + USB_PHY_UTMI_CTL_1);
2289d5f51dcSAl Cooper 	reg &= ~USB_PHY_UTMI_CTL_1_PHY_MODE_MASK;
2299d5f51dcSAl Cooper 	reg |= params->mode << USB_PHY_UTMI_CTL_1_PHY_MODE_SHIFT;
2309d5f51dcSAl Cooper 	brcm_usb_writel(reg, usb_phy + USB_PHY_UTMI_CTL_1);
2319d5f51dcSAl Cooper 
2329d5f51dcSAl Cooper 	/* Fix the incorrect default */
2339d5f51dcSAl Cooper 	reg = brcm_usb_readl(ctrl + USB_CTRL_SETUP);
2349d5f51dcSAl Cooper 	reg &= ~USB_CTRL_SETUP_tca_drv_sel_MASK;
2359d5f51dcSAl Cooper 	brcm_usb_writel(reg, ctrl + USB_CTRL_SETUP);
2369d5f51dcSAl Cooper 
2379d5f51dcSAl Cooper 	usb_init_common(params);
2389d5f51dcSAl Cooper 
239fc430aeaSAl Cooper 	/*
240*bed63b63SAl Cooper 	 * The BDC controller will get occasional failures with
241*bed63b63SAl Cooper 	 * the default "Read Transaction Size" of 6 (1024 bytes).
242*bed63b63SAl Cooper 	 * Set it to 4 (256 bytes).
243*bed63b63SAl Cooper 	 */
244*bed63b63SAl Cooper 	if ((params->mode != USB_CTLR_MODE_HOST) && bdc_ec) {
245*bed63b63SAl Cooper 		reg = brcm_usb_readl(bdc_ec + BDC_EC_AXIRDA);
246*bed63b63SAl Cooper 		reg &= ~BDC_EC_AXIRDA_RTS_MASK;
247*bed63b63SAl Cooper 		reg |= (0x4 << BDC_EC_AXIRDA_RTS_SHIFT);
248*bed63b63SAl Cooper 		brcm_usb_writel(reg, bdc_ec + BDC_EC_AXIRDA);
249*bed63b63SAl Cooper 	}
250*bed63b63SAl Cooper 
251*bed63b63SAl Cooper 	/*
252fc430aeaSAl Cooper 	 * Disable FSM, otherwise the PHY will auto suspend when no
253fc430aeaSAl Cooper 	 * device is connected and will be reset on resume.
254fc430aeaSAl Cooper 	 */
255fc430aeaSAl Cooper 	reg = brcm_usb_readl(usb_phy + USB_PHY_UTMI_CTL_1);
256fc430aeaSAl Cooper 	reg &= ~USB_PHY_UTMI_CTL_1_POWER_UP_FSM_EN_MASK;
257fc430aeaSAl Cooper 	brcm_usb_writel(reg, usb_phy + USB_PHY_UTMI_CTL_1);
258fc430aeaSAl Cooper 
2599d5f51dcSAl Cooper 	usb2_eye_fix_7211b0(params);
2609d5f51dcSAl Cooper }
2619d5f51dcSAl Cooper 
2624e5b9c9aSAl Cooper static void usb_init_xhci(struct brcm_usb_init_params *params)
2634e5b9c9aSAl Cooper {
2644e5b9c9aSAl Cooper 	pr_debug("%s\n", __func__);
2654e5b9c9aSAl Cooper 
2664e5b9c9aSAl Cooper 	xhci_soft_reset(params, 0);
2674e5b9c9aSAl Cooper }
2684e5b9c9aSAl Cooper 
2694e5b9c9aSAl Cooper static void usb_uninit_common(struct brcm_usb_init_params *params)
2704e5b9c9aSAl Cooper {
2719d5f51dcSAl Cooper 	void __iomem *ctrl = params->regs[BRCM_REGS_CTRL];
2724e5b9c9aSAl Cooper 
2734e5b9c9aSAl Cooper 	pr_debug("%s\n", __func__);
2744e5b9c9aSAl Cooper 
2754e5b9c9aSAl Cooper 	USB_CTRL_SET(ctrl, USB_PM, USB_PWRDN);
2764e5b9c9aSAl Cooper 
2774e5b9c9aSAl Cooper }
2784e5b9c9aSAl Cooper 
2794e5b9c9aSAl Cooper static void usb_uninit_xhci(struct brcm_usb_init_params *params)
2804e5b9c9aSAl Cooper {
2814e5b9c9aSAl Cooper 
2824e5b9c9aSAl Cooper 	pr_debug("%s\n", __func__);
2834e5b9c9aSAl Cooper 
2844e5b9c9aSAl Cooper 	xhci_soft_reset(params, 1);
2854e5b9c9aSAl Cooper }
2864e5b9c9aSAl Cooper 
2874e5b9c9aSAl Cooper static int usb_get_dual_select(struct brcm_usb_init_params *params)
2884e5b9c9aSAl Cooper {
2899d5f51dcSAl Cooper 	void __iomem *ctrl = params->regs[BRCM_REGS_CTRL];
2904e5b9c9aSAl Cooper 	u32 reg = 0;
2914e5b9c9aSAl Cooper 
2924e5b9c9aSAl Cooper 	pr_debug("%s\n", __func__);
2934e5b9c9aSAl Cooper 
2944e5b9c9aSAl Cooper 	reg = brcm_usb_readl(USB_CTRL_REG(ctrl, USB_DEVICE_CTL1));
2954e5b9c9aSAl Cooper 	reg &= USB_CTRL_MASK(USB_DEVICE_CTL1, PORT_MODE);
2964e5b9c9aSAl Cooper 	return reg;
2974e5b9c9aSAl Cooper }
2984e5b9c9aSAl Cooper 
2994e5b9c9aSAl Cooper static void usb_set_dual_select(struct brcm_usb_init_params *params, int mode)
3004e5b9c9aSAl Cooper {
3019d5f51dcSAl Cooper 	void __iomem *ctrl = params->regs[BRCM_REGS_CTRL];
3024e5b9c9aSAl Cooper 	u32 reg;
3034e5b9c9aSAl Cooper 
3044e5b9c9aSAl Cooper 	pr_debug("%s\n", __func__);
3054e5b9c9aSAl Cooper 
3064e5b9c9aSAl Cooper 	reg = brcm_usb_readl(USB_CTRL_REG(ctrl, USB_DEVICE_CTL1));
3074e5b9c9aSAl Cooper 	reg &= ~USB_CTRL_MASK(USB_DEVICE_CTL1, PORT_MODE);
3084e5b9c9aSAl Cooper 	reg |= mode;
3094e5b9c9aSAl Cooper 	brcm_usb_writel(reg, USB_CTRL_REG(ctrl, USB_DEVICE_CTL1));
3104e5b9c9aSAl Cooper }
3114e5b9c9aSAl Cooper 
3124e5b9c9aSAl Cooper 
3134e5b9c9aSAl Cooper static const struct brcm_usb_init_ops bcm7216_ops = {
3144e5b9c9aSAl Cooper 	.init_ipp = usb_init_ipp,
3154e5b9c9aSAl Cooper 	.init_common = usb_init_common,
3164e5b9c9aSAl Cooper 	.init_xhci = usb_init_xhci,
3174e5b9c9aSAl Cooper 	.uninit_common = usb_uninit_common,
3184e5b9c9aSAl Cooper 	.uninit_xhci = usb_uninit_xhci,
3194e5b9c9aSAl Cooper 	.get_dual_select = usb_get_dual_select,
3204e5b9c9aSAl Cooper 	.set_dual_select = usb_set_dual_select,
3214e5b9c9aSAl Cooper };
3224e5b9c9aSAl Cooper 
3239d5f51dcSAl Cooper static const struct brcm_usb_init_ops bcm7211b0_ops = {
3249d5f51dcSAl Cooper 	.init_ipp = usb_init_ipp,
3259d5f51dcSAl Cooper 	.init_common = usb_init_common_7211b0,
3269d5f51dcSAl Cooper 	.init_xhci = usb_init_xhci,
3279d5f51dcSAl Cooper 	.uninit_common = usb_uninit_common,
3289d5f51dcSAl Cooper 	.uninit_xhci = usb_uninit_xhci,
3299d5f51dcSAl Cooper 	.get_dual_select = usb_get_dual_select,
3309d5f51dcSAl Cooper 	.set_dual_select = usb_set_dual_select,
3319d5f51dcSAl Cooper };
3329d5f51dcSAl Cooper 
3334e5b9c9aSAl Cooper void brcm_usb_dvr_init_7216(struct brcm_usb_init_params *params)
3344e5b9c9aSAl Cooper {
3354e5b9c9aSAl Cooper 
3364e5b9c9aSAl Cooper 	pr_debug("%s\n", __func__);
3374e5b9c9aSAl Cooper 
3384e5b9c9aSAl Cooper 	params->family_name = "7216";
3394e5b9c9aSAl Cooper 	params->ops = &bcm7216_ops;
3404e5b9c9aSAl Cooper }
3419d5f51dcSAl Cooper 
3429d5f51dcSAl Cooper void brcm_usb_dvr_init_7211b0(struct brcm_usb_init_params *params)
3439d5f51dcSAl Cooper {
3449d5f51dcSAl Cooper 
3459d5f51dcSAl Cooper 	pr_debug("%s\n", __func__);
3469d5f51dcSAl Cooper 
3479d5f51dcSAl Cooper 	params->family_name = "7211";
3489d5f51dcSAl Cooper 	params->ops = &bcm7211b0_ops;
3499d5f51dcSAl Cooper }
350