Home | History | Annotate | Download | only in phy
      1 // SPDX-License-Identifier: GPL-2.0+
      2 /*
      3  * Copyright (C) 2017
      4  * Broadcom
      5  * Florian Fainelli <f.fainelli (at) gmail.com>
      6  */
      7 
      8 /*
      9  * PHY driver for Broadcom BCM53xx (roboswitch) Ethernet switches.
     10  *
     11  * This driver configures the b53 for basic use as a PHY. The switch supports
     12  * vendor tags and VLAN configuration that can affect the switching decisions.
     13  * This driver uses a simple configuration in which all ports are only allowed
     14  * to send frames to the CPU port and receive frames from the CPU port this
     15  * providing port isolation (no cross talk).
     16  *
     17  * The configuration determines which PHY ports to activate using the
     18  * CONFIG_B53_PHY_PORTS bitmask. Set bit N will active port N and so on.
     19  *
     20  * This driver was written primarily for the Lamobo R1 platform using a BCM53152
     21  * switch but the BCM53xx being largely register compatible, extending it to
     22  * cover other switches would be trivial.
     23  */
     24 
     25 #include <common.h>
     26 
     27 #include <errno.h>
     28 #include <malloc.h>
     29 #include <miiphy.h>
     30 #include <netdev.h>
     31 
     32 /* Pseudo-PHY address (non configurable) to access internal registers */
     33 #define BRCM_PSEUDO_PHY_ADDR		30
     34 
     35 /* Maximum number of ports possible */
     36 #define B53_N_PORTS			9
     37 
     38 #define B53_CTRL_PAGE			0x00 /* Control */
     39 #define B53_MGMT_PAGE			0x02 /* Management Mode */
     40 /* Port VLAN Page */
     41 #define B53_PVLAN_PAGE			0x31
     42 
     43 /* Control Page registers */
     44 #define B53_PORT_CTRL(i)		(0x00 + (i))
     45 #define   PORT_CTRL_RX_DISABLE		BIT(0)
     46 #define   PORT_CTRL_TX_DISABLE		BIT(1)
     47 #define   PORT_CTRL_RX_BCST_EN		BIT(2) /* Broadcast RX (P8 only) */
     48 #define   PORT_CTRL_RX_MCST_EN		BIT(3) /* Multicast RX (P8 only) */
     49 #define   PORT_CTRL_RX_UCST_EN		BIT(4) /* Unicast RX (P8 only) */
     50 
     51 /* Switch Mode Control Register (8 bit) */
     52 #define B53_SWITCH_MODE			0x0b
     53 #define   SM_SW_FWD_MODE		BIT(0)	/* 1 = Managed Mode */
     54 #define   SM_SW_FWD_EN			BIT(1)	/* Forwarding Enable */
     55 
     56 /* IMP Port state override register (8 bit) */
     57 #define B53_PORT_OVERRIDE_CTRL		0x0e
     58 #define   PORT_OVERRIDE_LINK		BIT(0)
     59 #define   PORT_OVERRIDE_FULL_DUPLEX	BIT(1) /* 0 = Half Duplex */
     60 #define   PORT_OVERRIDE_SPEED_S		2
     61 #define   PORT_OVERRIDE_SPEED_10M	(0 << PORT_OVERRIDE_SPEED_S)
     62 #define   PORT_OVERRIDE_SPEED_100M	(1 << PORT_OVERRIDE_SPEED_S)
     63 #define   PORT_OVERRIDE_SPEED_1000M	(2 << PORT_OVERRIDE_SPEED_S)
     64 /* BCM5325 only */
     65 #define   PORT_OVERRIDE_RV_MII_25	BIT(4)
     66 #define   PORT_OVERRIDE_RX_FLOW		BIT(4)
     67 #define   PORT_OVERRIDE_TX_FLOW		BIT(5)
     68 /* BCM5301X only, requires setting 1000M */
     69 #define   PORT_OVERRIDE_SPEED_2000M	BIT(6)
     70 #define   PORT_OVERRIDE_EN		BIT(7) /* Use the register contents */
     71 
     72 #define B53_RGMII_CTRL_IMP		0x60
     73 #define   RGMII_CTRL_ENABLE_GMII	BIT(7)
     74 #define   RGMII_CTRL_TIMING_SEL		BIT(2)
     75 #define   RGMII_CTRL_DLL_RXC		BIT(1)
     76 #define   RGMII_CTRL_DLL_TXC		BIT(0)
     77 
     78 /* Switch control (8 bit) */
     79 #define B53_SWITCH_CTRL			0x22
     80 #define  B53_MII_DUMB_FWDG_EN		BIT(6)
     81 
     82 /* Software reset register (8 bit) */
     83 #define B53_SOFTRESET			0x79
     84 #define   SW_RST			BIT(7)
     85 #define   EN_CH_RST			BIT(6)
     86 #define   EN_SW_RST			BIT(4)
     87 
     88 /* Fast Aging Control register (8 bit) */
     89 #define B53_FAST_AGE_CTRL		0x88
     90 #define   FAST_AGE_STATIC		BIT(0)
     91 #define   FAST_AGE_DYNAMIC		BIT(1)
     92 #define   FAST_AGE_PORT			BIT(2)
     93 #define   FAST_AGE_VLAN			BIT(3)
     94 #define   FAST_AGE_STP			BIT(4)
     95 #define   FAST_AGE_MC			BIT(5)
     96 #define   FAST_AGE_DONE			BIT(7)
     97 
     98 /* Port VLAN mask (16 bit) IMP port is always 8, also on 5325 & co */
     99 #define B53_PVLAN_PORT_MASK(i)		((i) * 2)
    100 
    101 /* MII registers */
    102 #define REG_MII_PAGE    0x10    /* MII Page register */
    103 #define REG_MII_ADDR    0x11    /* MII Address register */
    104 #define REG_MII_DATA0   0x18    /* MII Data register 0 */
    105 #define REG_MII_DATA1   0x19    /* MII Data register 1 */
    106 #define REG_MII_DATA2   0x1a    /* MII Data register 2 */
    107 #define REG_MII_DATA3   0x1b    /* MII Data register 3 */
    108 
    109 #define REG_MII_PAGE_ENABLE     BIT(0)
    110 #define REG_MII_ADDR_WRITE      BIT(0)
    111 #define REG_MII_ADDR_READ       BIT(1)
    112 
    113 struct b53_device {
    114 	struct mii_dev	*bus;
    115 	unsigned int cpu_port;
    116 };
    117 
    118 static int b53_mdio_op(struct mii_dev *bus, u8 page, u8 reg, u16 op)
    119 {
    120 	int ret;
    121 	int i;
    122 	u16 v;
    123 
    124 	/* set page number */
    125 	v = (page << 8) | REG_MII_PAGE_ENABLE;
    126 	ret = bus->write(bus, BRCM_PSEUDO_PHY_ADDR, MDIO_DEVAD_NONE,
    127 			 REG_MII_PAGE, v);
    128 	if (ret)
    129 		return ret;
    130 
    131 	/* set register address */
    132 	v = (reg << 8) | op;
    133 	ret = bus->write(bus, BRCM_PSEUDO_PHY_ADDR, MDIO_DEVAD_NONE,
    134 			 REG_MII_ADDR, v);
    135 	if (ret)
    136 		return ret;
    137 
    138 	/* check if operation completed */
    139 	for (i = 0; i < 5; ++i) {
    140 		v = bus->read(bus, BRCM_PSEUDO_PHY_ADDR, MDIO_DEVAD_NONE,
    141 			      REG_MII_ADDR);
    142 		if (!(v & (REG_MII_ADDR_WRITE | REG_MII_ADDR_READ)))
    143 			break;
    144 
    145 		udelay(100);
    146 	}
    147 
    148 	if (i == 5)
    149 		return -EIO;
    150 
    151 	return 0;
    152 }
    153 
    154 static int b53_mdio_read8(struct mii_dev *bus, u8 page, u8 reg, u8 *val)
    155 {
    156 	int ret;
    157 
    158 	ret = b53_mdio_op(bus, page, reg, REG_MII_ADDR_READ);
    159 	if (ret)
    160 		return ret;
    161 
    162 	*val = bus->read(bus, BRCM_PSEUDO_PHY_ADDR, MDIO_DEVAD_NONE,
    163 			 REG_MII_DATA0) & 0xff;
    164 
    165 	return 0;
    166 }
    167 
    168 static int b53_mdio_read16(struct mii_dev *bus, u8 page, u8 reg, u16 *val)
    169 {
    170 	int ret;
    171 
    172 	ret = b53_mdio_op(bus, page, reg, REG_MII_ADDR_READ);
    173 	if (ret)
    174 		return ret;
    175 
    176 	*val = bus->read(bus, BRCM_PSEUDO_PHY_ADDR, MDIO_DEVAD_NONE,
    177 			 REG_MII_DATA0);
    178 
    179 	return 0;
    180 }
    181 
    182 static int b53_mdio_read32(struct mii_dev *bus, u8 page, u8 reg, u32 *val)
    183 {
    184 	int ret;
    185 
    186 	ret = b53_mdio_op(bus, page, reg, REG_MII_ADDR_READ);
    187 	if (ret)
    188 		return ret;
    189 
    190 	*val = bus->read(bus, BRCM_PSEUDO_PHY_ADDR, MDIO_DEVAD_NONE,
    191 			 REG_MII_DATA0);
    192 	*val |= bus->read(bus, BRCM_PSEUDO_PHY_ADDR, MDIO_DEVAD_NONE,
    193 			  REG_MII_DATA1) << 16;
    194 
    195 	return 0;
    196 }
    197 
    198 static int b53_mdio_read48(struct mii_dev *bus, u8 page, u8 reg, u64 *val)
    199 {
    200 	u64 temp = 0;
    201 	int i;
    202 	int ret;
    203 
    204 	ret = b53_mdio_op(bus, page, reg, REG_MII_ADDR_READ);
    205 	if (ret)
    206 		return ret;
    207 
    208 	for (i = 2; i >= 0; i--) {
    209 		temp <<= 16;
    210 		temp |= bus->read(bus, BRCM_PSEUDO_PHY_ADDR, MDIO_DEVAD_NONE,
    211 				  REG_MII_DATA0 + i);
    212 	}
    213 
    214 	*val = temp;
    215 
    216 	return 0;
    217 }
    218 
    219 static int b53_mdio_read64(struct mii_dev *bus, u8 page, u8 reg, u64 *val)
    220 {
    221 	u64 temp = 0;
    222 	int i;
    223 	int ret;
    224 
    225 	ret = b53_mdio_op(bus, page, reg, REG_MII_ADDR_READ);
    226 	if (ret)
    227 		return ret;
    228 
    229 	for (i = 3; i >= 0; i--) {
    230 		temp <<= 16;
    231 		temp |= bus->read(bus, BRCM_PSEUDO_PHY_ADDR, MDIO_DEVAD_NONE,
    232 				  REG_MII_DATA0 + i);
    233 	}
    234 
    235 	*val = temp;
    236 
    237 	return 0;
    238 }
    239 
    240 static int b53_mdio_write8(struct mii_dev *bus, u8 page, u8 reg, u8 value)
    241 {
    242 	int ret;
    243 
    244 	ret = bus->write(bus, BRCM_PSEUDO_PHY_ADDR, MDIO_DEVAD_NONE,
    245 			 REG_MII_DATA0, value);
    246 	if (ret)
    247 		return ret;
    248 
    249 	return b53_mdio_op(bus, page, reg, REG_MII_ADDR_WRITE);
    250 }
    251 
    252 static int b53_mdio_write16(struct mii_dev *bus, u8 page, u8 reg,
    253 			    u16 value)
    254 {
    255 	int ret;
    256 
    257 	ret = bus->write(bus, BRCM_PSEUDO_PHY_ADDR, MDIO_DEVAD_NONE,
    258 			 REG_MII_DATA0, value);
    259 	if (ret)
    260 		return ret;
    261 
    262 	return b53_mdio_op(bus, page, reg, REG_MII_ADDR_WRITE);
    263 }
    264 
    265 static int b53_mdio_write32(struct mii_dev *bus, u8 page, u8 reg,
    266 			    u32 value)
    267 {
    268 	unsigned int i;
    269 	u32 temp = value;
    270 
    271 	for (i = 0; i < 2; i++) {
    272 		int ret = bus->write(bus, BRCM_PSEUDO_PHY_ADDR,
    273 				     MDIO_DEVAD_NONE,
    274 				     REG_MII_DATA0 + i, temp & 0xffff);
    275 		if (ret)
    276 			return ret;
    277 		temp >>= 16;
    278 	}
    279 
    280 	return b53_mdio_op(bus, page, reg, REG_MII_ADDR_WRITE);
    281 }
    282 
    283 static int b53_mdio_write48(struct mii_dev *bus, u8 page, u8 reg,
    284 			    u64 value)
    285 {
    286 	unsigned int i;
    287 	u64 temp = value;
    288 
    289 	for (i = 0; i < 3; i++) {
    290 		int ret = bus->write(bus, BRCM_PSEUDO_PHY_ADDR,
    291 				     MDIO_DEVAD_NONE,
    292 				     REG_MII_DATA0 + i, temp & 0xffff);
    293 		if (ret)
    294 			return ret;
    295 		temp >>= 16;
    296 	}
    297 
    298 	return b53_mdio_op(bus, page, reg, REG_MII_ADDR_WRITE);
    299 }
    300 
    301 static int b53_mdio_write64(struct mii_dev *bus, u8 page, u8 reg,
    302 			    u64 value)
    303 {
    304 	unsigned int i;
    305 	u64 temp = value;
    306 
    307 	for (i = 0; i < 4; i++) {
    308 		int ret = bus->write(bus, BRCM_PSEUDO_PHY_ADDR,
    309 				     MDIO_DEVAD_NONE,
    310 				     REG_MII_DATA0 + i, temp & 0xffff);
    311 		if (ret)
    312 			return ret;
    313 		temp >>= 16;
    314 	}
    315 
    316 	return b53_mdio_op(bus, page, reg, REG_MII_ADDR_WRITE);
    317 }
    318 
    319 static inline int b53_read8(struct b53_device *dev, u8 page,
    320 			    u8 reg, u8 *value)
    321 {
    322 	return b53_mdio_read8(dev->bus, page, reg, value);
    323 }
    324 
    325 static inline int b53_read16(struct b53_device *dev, u8 page,
    326 			     u8 reg, u16 *value)
    327 {
    328 	return b53_mdio_read16(dev->bus, page, reg, value);
    329 }
    330 
    331 static inline int b53_read32(struct b53_device *dev, u8 page,
    332 			     u8 reg, u32 *value)
    333 {
    334 	return b53_mdio_read32(dev->bus, page, reg, value);
    335 }
    336 
    337 static inline int b53_read48(struct b53_device *dev, u8 page,
    338 			     u8 reg, u64 *value)
    339 {
    340 	return b53_mdio_read48(dev->bus, page, reg, value);
    341 }
    342 
    343 static inline int b53_read64(struct b53_device *dev, u8 page,
    344 			     u8 reg, u64 *value)
    345 {
    346 	return b53_mdio_read64(dev->bus, page, reg, value);
    347 }
    348 
    349 static inline int b53_write8(struct b53_device *dev, u8 page,
    350 			     u8 reg, u8 value)
    351 {
    352 	return b53_mdio_write8(dev->bus, page, reg, value);
    353 }
    354 
    355 static inline int b53_write16(struct b53_device *dev, u8 page,
    356 			      u8 reg, u16 value)
    357 {
    358 	return b53_mdio_write16(dev->bus, page, reg, value);
    359 }
    360 
    361 static inline int b53_write32(struct b53_device *dev, u8 page,
    362 			      u8 reg, u32 value)
    363 {
    364 	return b53_mdio_write32(dev->bus, page, reg, value);
    365 }
    366 
    367 static inline int b53_write48(struct b53_device *dev, u8 page,
    368 			      u8 reg, u64 value)
    369 {
    370 	return b53_mdio_write48(dev->bus, page, reg, value);
    371 }
    372 
    373 static inline int b53_write64(struct b53_device *dev, u8 page,
    374 			      u8 reg, u64 value)
    375 {
    376 	return b53_mdio_write64(dev->bus, page, reg, value);
    377 }
    378 
    379 static int b53_flush_arl(struct b53_device *dev, u8 mask)
    380 {
    381 	unsigned int i;
    382 
    383 	b53_write8(dev, B53_CTRL_PAGE, B53_FAST_AGE_CTRL,
    384 		   FAST_AGE_DONE | FAST_AGE_DYNAMIC | mask);
    385 
    386 	for (i = 0; i < 10; i++) {
    387 		u8 fast_age_ctrl;
    388 
    389 		b53_read8(dev, B53_CTRL_PAGE, B53_FAST_AGE_CTRL,
    390 			  &fast_age_ctrl);
    391 
    392 		if (!(fast_age_ctrl & FAST_AGE_DONE))
    393 			goto out;
    394 
    395 		mdelay(1);
    396 	}
    397 
    398 	return -ETIMEDOUT;
    399 out:
    400 	/* Only age dynamic entries (default behavior) */
    401 	b53_write8(dev, B53_CTRL_PAGE, B53_FAST_AGE_CTRL, FAST_AGE_DYNAMIC);
    402 	return 0;
    403 }
    404 
    405 static int b53_switch_reset(struct phy_device *phydev)
    406 {
    407 	struct b53_device *dev = phydev->priv;
    408 	unsigned int timeout = 1000;
    409 	u8 mgmt;
    410 	u8 reg;
    411 
    412 	b53_read8(dev, B53_CTRL_PAGE, B53_SOFTRESET, &reg);
    413 	reg |= SW_RST | EN_SW_RST | EN_CH_RST;
    414 	b53_write8(dev, B53_CTRL_PAGE, B53_SOFTRESET, reg);
    415 
    416 	do {
    417 		b53_read8(dev, B53_CTRL_PAGE, B53_SOFTRESET, &reg);
    418 		if (!(reg & SW_RST))
    419 			break;
    420 
    421 		mdelay(1);
    422 	} while (timeout-- > 0);
    423 
    424 	if (timeout == 0)
    425 		return -ETIMEDOUT;
    426 
    427 	b53_read8(dev, B53_CTRL_PAGE, B53_SWITCH_MODE, &mgmt);
    428 
    429 	if (!(mgmt & SM_SW_FWD_EN)) {
    430 		mgmt &= ~SM_SW_FWD_MODE;
    431 		mgmt |= SM_SW_FWD_EN;
    432 
    433 		b53_write8(dev, B53_CTRL_PAGE, B53_SWITCH_MODE, mgmt);
    434 		b53_read8(dev, B53_CTRL_PAGE, B53_SWITCH_MODE, &mgmt);
    435 
    436 		if (!(mgmt & SM_SW_FWD_EN)) {
    437 			printf("Failed to enable switch!\n");
    438 			return -EINVAL;
    439 		}
    440 	}
    441 
    442 	/* Include IMP port in dumb forwarding mode when no tagging protocol
    443 	 * is configured
    444 	 */
    445 	b53_read8(dev, B53_CTRL_PAGE, B53_SWITCH_CTRL, &mgmt);
    446 	mgmt |= B53_MII_DUMB_FWDG_EN;
    447 	b53_write8(dev, B53_CTRL_PAGE, B53_SWITCH_CTRL, mgmt);
    448 
    449 	return b53_flush_arl(dev, FAST_AGE_STATIC);
    450 }
    451 
    452 static void b53_enable_cpu_port(struct phy_device *phydev)
    453 {
    454 	struct b53_device *dev = phydev->priv;
    455 	u8 port_ctrl;
    456 
    457 	port_ctrl = PORT_CTRL_RX_BCST_EN |
    458 		    PORT_CTRL_RX_MCST_EN |
    459 		    PORT_CTRL_RX_UCST_EN;
    460 	b53_write8(dev, B53_CTRL_PAGE, B53_PORT_CTRL(dev->cpu_port), port_ctrl);
    461 
    462 	port_ctrl = PORT_OVERRIDE_EN | PORT_OVERRIDE_LINK |
    463 		    PORT_OVERRIDE_FULL_DUPLEX | PORT_OVERRIDE_SPEED_1000M;
    464 	b53_write8(dev, B53_CTRL_PAGE, B53_PORT_OVERRIDE_CTRL, port_ctrl);
    465 
    466 	b53_read8(dev, B53_CTRL_PAGE, B53_RGMII_CTRL_IMP, &port_ctrl);
    467 }
    468 
    469 static void b53_imp_vlan_setup(struct b53_device *dev, int cpu_port)
    470 {
    471 	unsigned int port;
    472 	u16 pvlan;
    473 
    474 	/* Enable the IMP port to be in the same VLAN as the other ports
    475 	 * on a per-port basis such that we only have Port i and IMP in
    476 	 * the same VLAN.
    477 	 */
    478 	for (port = 0; port < B53_N_PORTS; port++) {
    479 		if (!((1 << port) & CONFIG_B53_PHY_PORTS))
    480 			continue;
    481 
    482 		b53_read16(dev, B53_PVLAN_PAGE, B53_PVLAN_PORT_MASK(port),
    483 			   &pvlan);
    484 		pvlan |= BIT(cpu_port);
    485 		b53_write16(dev, B53_PVLAN_PAGE, B53_PVLAN_PORT_MASK(port),
    486 			    pvlan);
    487 	}
    488 }
    489 
    490 static int b53_port_enable(struct phy_device *phydev, unsigned int port)
    491 {
    492 	struct b53_device *dev = phydev->priv;
    493 	unsigned int cpu_port = dev->cpu_port;
    494 	u16 pvlan;
    495 
    496 	/* Clear the Rx and Tx disable bits and set to no spanning tree */
    497 	b53_write8(dev, B53_CTRL_PAGE, B53_PORT_CTRL(port), 0);
    498 
    499 	/* Set this port, and only this one to be in the default VLAN */
    500 	b53_read16(dev, B53_PVLAN_PAGE, B53_PVLAN_PORT_MASK(port), &pvlan);
    501 	pvlan &= ~0x1ff;
    502 	pvlan |= BIT(port);
    503 	b53_write16(dev, B53_PVLAN_PAGE, B53_PVLAN_PORT_MASK(port), pvlan);
    504 
    505 	b53_imp_vlan_setup(dev, cpu_port);
    506 
    507 	return 0;
    508 }
    509 
    510 static int b53_switch_init(struct phy_device *phydev)
    511 {
    512 	static int init;
    513 	int ret;
    514 
    515 	if (init)
    516 		return 0;
    517 
    518 	ret = b53_switch_reset(phydev);
    519 	if (ret < 0)
    520 		return ret;
    521 
    522 	b53_enable_cpu_port(phydev);
    523 
    524 	init = 1;
    525 
    526 	return 0;
    527 }
    528 
    529 static int b53_probe(struct phy_device *phydev)
    530 {
    531 	struct b53_device *dev;
    532 	int ret;
    533 
    534 	dev = malloc(sizeof(*dev));
    535 	if (!dev)
    536 		return -ENOMEM;
    537 
    538 	memset(dev, 0, sizeof(*dev));
    539 
    540 	phydev->priv = dev;
    541 	dev->bus = phydev->bus;
    542 	dev->cpu_port = CONFIG_B53_CPU_PORT;
    543 
    544 	ret = b53_switch_reset(phydev);
    545 	if (ret < 0)
    546 		return ret;
    547 
    548 	return 0;
    549 }
    550 
    551 static int b53_phy_config(struct phy_device *phydev)
    552 {
    553 	unsigned int port;
    554 	int res;
    555 
    556 	res = b53_switch_init(phydev);
    557 	if (res < 0)
    558 		return res;
    559 
    560 	for (port = 0; port < B53_N_PORTS; port++) {
    561 		if (!((1 << port) & CONFIG_B53_PHY_PORTS))
    562 			continue;
    563 
    564 		res = b53_port_enable(phydev, port);
    565 		if (res < 0) {
    566 			printf("Error enabling port %i\n", port);
    567 			continue;
    568 		}
    569 
    570 		res = genphy_config_aneg(phydev);
    571 		if (res < 0) {
    572 			printf("Error setting PHY %i autoneg\n", port);
    573 			continue;
    574 		}
    575 
    576 		res = 0;
    577 	}
    578 
    579 	return res;
    580 }
    581 
    582 static int b53_phy_startup(struct phy_device *phydev)
    583 {
    584 	unsigned int port;
    585 	int res;
    586 
    587 	for (port = 0; port < B53_N_PORTS; port++) {
    588 		if (!((1 << port) & CONFIG_B53_PHY_PORTS))
    589 			continue;
    590 
    591 		phydev->addr = port;
    592 
    593 		res = genphy_startup(phydev);
    594 		if (res < 0)
    595 			continue;
    596 		else
    597 			break;
    598 	}
    599 
    600 	/* Since we are connected directly to the switch, hardcode the link
    601 	 * parameters to match those of the CPU port configured in
    602 	 * b53_enable_cpu_port, we cannot be dependent on the user-facing port
    603 	 * settings (e.g: 100Mbits/sec would not work here)
    604 	 */
    605 	phydev->speed = 1000;
    606 	phydev->duplex = 1;
    607 	phydev->link = 1;
    608 
    609 	return 0;
    610 }
    611 
    612 static struct phy_driver b53_driver = {
    613 	.name = "Broadcom BCM53125",
    614 	.uid = 0x03625c00,
    615 	.mask = 0xfffffc00,
    616 	.features = PHY_GBIT_FEATURES,
    617 	.probe = b53_probe,
    618 	.config = b53_phy_config,
    619 	.startup = b53_phy_startup,
    620 	.shutdown = &genphy_shutdown,
    621 };
    622 
    623 int phy_b53_init(void)
    624 {
    625 	phy_register(&b53_driver);
    626 
    627 	return 0;
    628 }
    629 
    630 int do_b53_reg_read(const char *name, int argc, char * const argv[])
    631 {
    632 	u8 page, offset, width;
    633 	struct mii_dev *bus;
    634 	int ret = -EINVAL;
    635 	u64 value64 = 0;
    636 	u32 value32 = 0;
    637 	u16 value16 = 0;
    638 	u8 value8 = 0;
    639 
    640 	bus = miiphy_get_dev_by_name(name);
    641 	if (!bus) {
    642 		printf("unable to find MDIO bus: %s\n", name);
    643 		return ret;
    644 	}
    645 
    646 	page = simple_strtoul(argv[1], NULL, 16);
    647 	offset = simple_strtoul(argv[2], NULL, 16);
    648 	width = simple_strtoul(argv[3], NULL, 10);
    649 
    650 	switch (width) {
    651 	case 8:
    652 		ret = b53_mdio_read8(bus, page, offset, &value8);
    653 		printf("page=0x%02x, offset=0x%02x, value=0x%02x\n",
    654 		       page, offset, value8);
    655 		break;
    656 	case 16:
    657 		ret = b53_mdio_read16(bus, page, offset, &value16);
    658 		printf("page=0x%02x, offset=0x%02x, value=0x%04x\n",
    659 		       page, offset, value16);
    660 		break;
    661 	case 32:
    662 		ret = b53_mdio_read32(bus, page, offset, &value32);
    663 		printf("page=0x%02x, offset=0x%02x, value=0x%08x\n",
    664 		       page, offset, value32);
    665 		break;
    666 	case 48:
    667 		ret = b53_mdio_read48(bus, page, offset, &value64);
    668 		printf("page=0x%02x, offset=0x%02x, value=0x%012llx\n",
    669 		       page, offset, value64);
    670 		break;
    671 	case 64:
    672 		ret = b53_mdio_read48(bus, page, offset, &value64);
    673 		printf("page=0x%02x, offset=0x%02x, value=0x%016llx\n",
    674 		       page, offset, value64);
    675 		break;
    676 	default:
    677 		printf("Unsupported width: %d\n", width);
    678 		break;
    679 	}
    680 
    681 	return ret;
    682 }
    683 
    684 int do_b53_reg_write(const char *name, int argc, char * const argv[])
    685 {
    686 	u8 page, offset, width;
    687 	struct mii_dev *bus;
    688 	int ret = -EINVAL;
    689 	u64 value64 = 0;
    690 	u32 value = 0;
    691 
    692 	bus = miiphy_get_dev_by_name(name);
    693 	if (!bus) {
    694 		printf("unable to find MDIO bus: %s\n", name);
    695 		return ret;
    696 	}
    697 
    698 	page = simple_strtoul(argv[1], NULL, 16);
    699 	offset = simple_strtoul(argv[2], NULL, 16);
    700 	width = simple_strtoul(argv[3], NULL, 10);
    701 	if (width == 48 || width == 64)
    702 		value64 = simple_strtoull(argv[4], NULL, 16);
    703 	else
    704 		value = simple_strtoul(argv[4], NULL, 16);
    705 
    706 	switch (width) {
    707 	case 8:
    708 		ret = b53_mdio_write8(bus, page, offset, value & 0xff);
    709 		break;
    710 	case 16:
    711 		ret = b53_mdio_write16(bus, page, offset, value);
    712 		break;
    713 	case 32:
    714 		ret = b53_mdio_write32(bus, page, offset, value);
    715 		break;
    716 	case 48:
    717 		ret = b53_mdio_write48(bus, page, offset, value64);
    718 		break;
    719 	case 64:
    720 		ret = b53_mdio_write64(bus, page, offset, value64);
    721 		break;
    722 	default:
    723 		printf("Unsupported width: %d\n", width);
    724 		break;
    725 	}
    726 
    727 	return ret;
    728 }
    729 
    730 int do_b53_reg(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
    731 {
    732 	const char *cmd, *mdioname;
    733 	int ret = 0;
    734 
    735 	if (argc < 2)
    736 		return cmd_usage(cmdtp);
    737 
    738 	cmd = argv[1];
    739 	--argc;
    740 	++argv;
    741 
    742 	if (!strcmp(cmd, "write")) {
    743 		if (argc < 4)
    744 			return cmd_usage(cmdtp);
    745 		mdioname = argv[1];
    746 		--argc;
    747 		++argv;
    748 		ret = do_b53_reg_write(mdioname, argc, argv);
    749 	} else if (!strcmp(cmd, "read")) {
    750 		if (argc < 5)
    751 			return cmd_usage(cmdtp);
    752 		mdioname = argv[1];
    753 		--argc;
    754 		++argv;
    755 		ret = do_b53_reg_read(mdioname, argc, argv);
    756 	} else {
    757 		return cmd_usage(cmdtp);
    758 	}
    759 
    760 	return ret;
    761 }
    762 
    763 U_BOOT_CMD(b53_reg, 7, 1, do_b53_reg,
    764 	   "Broadcom B53 switch register access",
    765 	   "write mdioname page (hex) offset (hex) width (dec) value (hex)\n"
    766 	   "read mdioname page (hex) offset (hex) width (dec)\n"
    767 	  );
    768