1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526
|
// SPDX-License-Identifier: GPL-2.0
/* Copyright (c) 2018, Broadcom */
/*
* This module contains USB PHY initialization for power up and S3 resume
* for newer Synopsys based USB hardware first used on the bcm7216.
*/
#include <linux/delay.h>
#include <linux/io.h>
#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_SATA_PRIORITY_MASK GENMASK(3, 0)
#define PIARBCTL_MISC_CAM0_MEM_PAGE_MASK GENMASK(7, 4)
#define PIARBCTL_MISC_CAM1_MEM_PAGE_MASK GENMASK(11, 8)
#define PIARBCTL_MISC_USB_MEM_PAGE_MASK GENMASK(15, 12)
#define PIARBCTL_MISC_USB_PRIORITY_MASK GENMASK(19, 16)
#define PIARBCTL_MISC_USB_4G_SDRAM_MASK BIT(29)
#define PIARBCTL_MISC_USB_SELECT_MASK BIT(30)
#define PIARBCTL_MISC_SECURE_MASK BIT(31)
#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_IOC_MASK BIT(4)
#define USB_CTRL_SETUP_IPP_MASK BIT(5)
#define USB_CTRL_SETUP_SOFT_SHUTDOWN_MASK BIT(9)
#define USB_CTRL_SETUP_SCB1_EN_MASK BIT(14)
#define USB_CTRL_SETUP_SCB2_EN_MASK BIT(15)
#define USB_CTRL_SETUP_tca_drv_sel_MASK BIT(24)
#define USB_CTRL_SETUP_STRAP_IPP_SEL_MASK BIT(25)
#define USB_CTRL_USB_PM 0x04
#define USB_CTRL_USB_PM_REF_S2_CLK_SWITCH_EN_MASK BIT(1)
#define USB_CTRL_USB_PM_UTMI_S2_CLK_SWITCH_EN_MASK BIT(2)
#define USB_CTRL_USB_PM_XHC_S2_CLK_SWITCH_EN_MASK BIT(3)
#define USB_CTRL_USB_PM_XHC_PME_EN_MASK BIT(4)
#define USB_CTRL_USB_PM_XHC_SOFT_RESETB_MASK BIT(22)
#define USB_CTRL_USB_PM_BDC_SOFT_RESETB_MASK BIT(23)
#define USB_CTRL_USB_PM_SOFT_RESET_MASK BIT(30)
#define USB_CTRL_USB_PM_USB_PWRDN_MASK BIT(31)
#define USB_CTRL_USB_PM_STATUS 0x08
#define USB_CTRL_USB_DEVICE_CTL1 0x10
#define USB_CTRL_USB_DEVICE_CTL1_PORT_MODE_MASK GENMASK(1, 0)
#define USB_CTRL_TEST_PORT_CTL 0x30
#define USB_CTRL_TEST_PORT_CTL_TPOUT_SEL_MASK GENMASK(7, 0)
#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 BIT(1)
#define USB_CTRL_CTLR_CSHCR 0x50
#define USB_CTRL_CTLR_CSHCR_ctl_pme_en_MASK BIT(18)
#define USB_CTRL_P0_U2PHY_CFG1 0x68
#define USB_CTRL_P0_U2PHY_CFG1_COMMONONN_MASK BIT(10)
#define USB_CTRL_P0_U2PHY_CFG2 0x6c
#define USB_CTRL_P0_U2PHY_CFG2_TXVREFTUNE0_MASK GENMASK(20, 17)
#define USB_CTRL_P0_U2PHY_CFG2_TXVREFTUNE0_SHIFT 17
#define USB_CTRL_P0_U2PHY_CFG2_TXRESTUNE0_MASK GENMASK(24, 23)
#define USB_CTRL_P0_U2PHY_CFG2_TXRESTUNE0_SHIFT 23
#define USB_CTRL_P0_U2PHY_CFG2_TXPREEMPAMPTUNE0_MASK GENMASK(26, 25)
#define USB_CTRL_P0_U2PHY_CFG2_TXPREEMPAMPTUNE0_SHIFT 25
/* Register definitions for the USB_PHY block in 7211b0 */
#define USB_PHY_PLL_CTL 0x00
#define USB_PHY_PLL_CTL_PLL_SUSPEND_MASK BIT(27)
#define USB_PHY_PLL_CTL_PLL_RESETB_MASK BIT(30)
#define USB_PHY_PLL_LDO_CTL 0x08
#define USB_PHY_PLL_LDO_CTL_AFE_BG_PWRDWNB_MASK BIT(0)
#define USB_PHY_PLL_LDO_CTL_AFE_LDO_PWRDWNB_MASK BIT(1)
#define USB_PHY_PLL_LDO_CTL_AFE_CORERDY_MASK BIT(2)
#define USB_PHY_UTMI_CTL_1 0x04
#define USB_PHY_UTMI_CTL_1_PHY_MODE_MASK GENMASK(3, 2)
#define USB_PHY_UTMI_CTL_1_PHY_MODE_SHIFT 2
#define USB_PHY_UTMI_CTL_1_POWER_UP_FSM_EN_MASK BIT(11)
#define USB_PHY_IDDQ 0x1c
#define USB_PHY_IDDQ_phy_iddq_MASK BIT(0)
#define USB_PHY_STATUS 0x20
#define USB_PHY_STATUS_pll_lock_MASK BIT(0)
/* 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
/* Register definitions for the BDC EC block in 7211b0 */
#define BDC_EC_AXIRDA 0x0c
#define BDC_EC_AXIRDA_RTS_MASK GENMASK(31, 28)
#define BDC_EC_AXIRDA_RTS_SHIFT 28
#define USB_XHCI_GBL_GUSB2PHYCFG 0x100
#define USB_XHCI_GBL_GUSB2PHYCFG_U2_FREECLK_EXISTS_MASK BIT(30)
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->regs[BRCM_REGS_CTRL];
void __iomem *xhci_gbl = params->regs[BRCM_REGS_XHCI_GBL];
/* Assert reset */
if (on_off) {
USB_CTRL_UNSET(ctrl, USB_PM, XHC_SOFT_RESETB);
/* De-assert reset */
} else {
USB_CTRL_SET(ctrl, USB_PM, XHC_SOFT_RESETB);
/* Required for COMMONONN to be set */
if (params->supported_port_modes != USB_CTLR_MODE_DRD)
USB_XHCI_GBL_UNSET(xhci_gbl, GUSB2PHYCFG,
U2_FREECLK_EXISTS);
}
}
static void usb_init_ipp(struct brcm_usb_init_params *params)
{
void __iomem *ctrl = params->regs[BRCM_REGS_CTRL];
u32 reg;
u32 orig_reg;
pr_debug("%s\n", __func__);
orig_reg = reg = brcm_usb_readl(USB_CTRL_REG(ctrl, SETUP));
if (params->ipp != 2)
/* override ipp strap pin (if it exits) */
reg &= ~(USB_CTRL_MASK(SETUP, STRAP_IPP_SEL));
/* Override the default OC and PP polarity */
reg &= ~(USB_CTRL_MASK(SETUP, IPP) | USB_CTRL_MASK(SETUP, IOC));
if (params->ioc)
reg |= USB_CTRL_MASK(SETUP, IOC);
if (params->ipp == 1)
reg |= USB_CTRL_MASK(SETUP, IPP);
brcm_usb_writel(reg, USB_CTRL_REG(ctrl, SETUP));
/*
* If we're changing IPP, make sure power is off long enough
* to turn off any connected devices.
*/
if ((reg ^ orig_reg) & USB_CTRL_MASK(SETUP, IPP))
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->regs[BRCM_REGS_CTRL];
pr_debug("%s\n", __func__);
if (USB_CTRL_MASK(USB_DEVICE_CTL1, PORT_MODE)) {
reg = brcm_usb_readl(USB_CTRL_REG(ctrl, USB_DEVICE_CTL1));
reg &= ~USB_CTRL_MASK(USB_DEVICE_CTL1, PORT_MODE);
reg |= params->port_mode;
brcm_usb_writel(reg, USB_CTRL_REG(ctrl, USB_DEVICE_CTL1));
}
switch (params->supported_port_modes) {
case USB_CTLR_MODE_HOST:
USB_CTRL_UNSET(ctrl, USB_PM, BDC_SOFT_RESETB);
break;
default:
USB_CTRL_UNSET(ctrl, USB_PM, BDC_SOFT_RESETB);
USB_CTRL_SET(ctrl, USB_PM, BDC_SOFT_RESETB);
break;
}
}
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_wake_enable_7216(struct brcm_usb_init_params *params,
bool enable)
{
void __iomem *ctrl = params->regs[BRCM_REGS_CTRL];
if (enable)
USB_CTRL_SET(ctrl, USB_PM, XHC_PME_EN);
else
USB_CTRL_UNSET(ctrl, USB_PM, XHC_PME_EN);
}
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];
void __iomem *bdc_ec = params->regs[BRCM_REGS_BDC_EC];
int timeout_ms = PHY_LOCK_TIMEOUT_MS;
u32 reg;
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);
}
/* Disable PLL auto suspend */
reg = brcm_usb_readl(usb_phy + USB_PHY_PLL_CTL);
reg |= USB_PHY_PLL_CTL_PLL_SUSPEND_MASK;
brcm_usb_writel(reg, usb_phy + USB_PHY_PLL_CTL);
/* Init the PHY */
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 */
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->supported_port_modes << USB_PHY_UTMI_CTL_1_PHY_MODE_SHIFT;
brcm_usb_writel(reg, usb_phy + USB_PHY_UTMI_CTL_1);
usb_init_common(params);
/*
* The BDC controller will get occasional failures with
* the default "Read Transaction Size" of 6 (1024 bytes).
* Set it to 4 (256 bytes).
*/
if ((params->supported_port_modes != USB_CTLR_MODE_HOST) && bdc_ec) {
reg = brcm_usb_readl(bdc_ec + BDC_EC_AXIRDA);
reg &= ~BDC_EC_AXIRDA_RTS_MASK;
reg |= (0x4 << BDC_EC_AXIRDA_RTS_SHIFT);
brcm_usb_writel(reg, bdc_ec + BDC_EC_AXIRDA);
}
/*
* Disable FSM, otherwise the PHY will auto suspend when no
* device is connected and will be reset on resume.
*/
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);
usb2_eye_fix_7211b0(params);
}
static void usb_init_common_7216(struct brcm_usb_init_params *params)
{
void __iomem *ctrl = params->regs[BRCM_REGS_CTRL];
USB_CTRL_UNSET(ctrl, USB_PM, XHC_S2_CLK_SWITCH_EN);
/*
* The PHY might be in a bad state if it is already powered
* up. Toggle the power just in case.
*/
USB_CTRL_SET(ctrl, USB_PM, USB_PWRDN);
USB_CTRL_UNSET(ctrl, USB_PM, USB_PWRDN);
/* 1 millisecond - for USB clocks to settle down */
usleep_range(1000, 2000);
/*
* Disable PHY when port is suspended
* Does not work in DRD mode
*/
if (params->supported_port_modes != USB_CTLR_MODE_DRD)
USB_CTRL_SET(ctrl, P0_U2PHY_CFG1, COMMONONN);
usb_wake_enable_7216(params, false);
usb_init_common(params);
}
static void usb_init_xhci(struct brcm_usb_init_params *params)
{
pr_debug("%s\n", __func__);
xhci_soft_reset(params, 0);
}
static void usb_uninit_common_7216(struct brcm_usb_init_params *params)
{
void __iomem *ctrl = params->regs[BRCM_REGS_CTRL];
pr_debug("%s\n", __func__);
if (params->wake_enabled) {
/* Switch to using slower clock during suspend to save power */
USB_CTRL_SET(ctrl, USB_PM, XHC_S2_CLK_SWITCH_EN);
usb_wake_enable_7216(params, true);
} else {
USB_CTRL_SET(ctrl, USB_PM, USB_PWRDN);
}
}
static void usb_init_common_74110(struct brcm_usb_init_params *params)
{
void __iomem *ctrl = params->regs[BRCM_REGS_CTRL];
u32 reg;
reg = brcm_usb_readl(USB_CTRL_REG(ctrl, USB_PM));
reg &= ~(USB_CTRL_MASK(USB_PM, REF_S2_CLK_SWITCH_EN) |
USB_CTRL_MASK(USB_PM, UTMI_S2_CLK_SWITCH_EN));
brcm_usb_writel(reg, USB_CTRL_REG(ctrl, USB_PM));
usb_init_common_7216(params);
reg = brcm_usb_readl(USB_CTRL_REG(ctrl, P0_U2PHY_CFG2));
reg &= ~(USB_CTRL_P0_U2PHY_CFG2_TXVREFTUNE0_MASK |
USB_CTRL_P0_U2PHY_CFG2_TXRESTUNE0_MASK |
USB_CTRL_P0_U2PHY_CFG2_TXPREEMPAMPTUNE0_MASK);
reg |= (0x6 << USB_CTRL_P0_U2PHY_CFG2_TXVREFTUNE0_SHIFT) |
(0x3 << USB_CTRL_P0_U2PHY_CFG2_TXRESTUNE0_SHIFT) |
(0x2 << USB_CTRL_P0_U2PHY_CFG2_TXPREEMPAMPTUNE0_SHIFT);
brcm_usb_writel(reg, USB_CTRL_REG(ctrl, P0_U2PHY_CFG2));
}
static void usb_uninit_common_74110(struct brcm_usb_init_params *params)
{
void __iomem *ctrl = params->regs[BRCM_REGS_CTRL];
u32 reg;
if (params->wake_enabled) {
reg = brcm_usb_readl(USB_CTRL_REG(ctrl, USB_PM));
reg |= (USB_CTRL_MASK(USB_PM, REF_S2_CLK_SWITCH_EN) |
USB_CTRL_MASK(USB_PM, UTMI_S2_CLK_SWITCH_EN));
brcm_usb_writel(reg, USB_CTRL_REG(ctrl, USB_PM));
}
usb_uninit_common_7216(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__);
if (!params->wake_enabled)
xhci_soft_reset(params, 1);
}
static int usb_get_dual_select(struct brcm_usb_init_params *params)
{
void __iomem *ctrl = params->regs[BRCM_REGS_CTRL];
u32 reg = 0;
pr_debug("%s\n", __func__);
reg = brcm_usb_readl(USB_CTRL_REG(ctrl, USB_DEVICE_CTL1));
reg &= USB_CTRL_MASK(USB_DEVICE_CTL1, PORT_MODE);
return reg;
}
static void usb_set_dual_select(struct brcm_usb_init_params *params)
{
void __iomem *ctrl = params->regs[BRCM_REGS_CTRL];
u32 reg;
pr_debug("%s\n", __func__);
reg = brcm_usb_readl(USB_CTRL_REG(ctrl, USB_DEVICE_CTL1));
reg &= ~USB_CTRL_MASK(USB_DEVICE_CTL1, PORT_MODE);
reg |= params->port_mode;
brcm_usb_writel(reg, USB_CTRL_REG(ctrl, USB_DEVICE_CTL1));
}
static const struct brcm_usb_init_ops bcm74110_ops = {
.init_ipp = usb_init_ipp,
.init_common = usb_init_common_74110,
.init_xhci = usb_init_xhci,
.uninit_common = usb_uninit_common_74110,
.uninit_xhci = usb_uninit_xhci,
.get_dual_select = usb_get_dual_select,
.set_dual_select = usb_set_dual_select,
};
static const struct brcm_usb_init_ops bcm7216_ops = {
.init_ipp = usb_init_ipp,
.init_common = usb_init_common_7216,
.init_xhci = usb_init_xhci,
.uninit_common = usb_uninit_common_7216,
.uninit_xhci = usb_uninit_xhci,
.get_dual_select = usb_get_dual_select,
.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_7211b0,
.uninit_xhci = usb_uninit_xhci,
.get_dual_select = usb_get_dual_select,
.set_dual_select = usb_set_dual_select,
};
void brcm_usb_dvr_init_74110(struct brcm_usb_init_params *params)
{
params->family_name = "74110";
params->ops = &bcm74110_ops;
}
void brcm_usb_dvr_init_7216(struct brcm_usb_init_params *params)
{
pr_debug("%s\n", __func__);
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;
}
|