Skip to content

Commit 09cb7df

Browse files
viviendavem330
authored andcommitted
net: dsa: mv88e6xxx: describe PHY page and SerDes
Add mv88e6xxx_phy_page_{read,write} routines and use them to access the SerDes PHY device registers. Signed-off-by: Vivien Didelot <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent e57e5e7 commit 09cb7df

File tree

2 files changed

+105
-17
lines changed

2 files changed

+105
-17
lines changed

drivers/net/dsa/mv88e6xxx/chip.c

Lines changed: 81 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -238,6 +238,74 @@ static int mv88e6xxx_phy_write(struct mv88e6xxx_chip *chip, int phy,
238238
return chip->phy_ops->write(chip, addr, reg, val);
239239
}
240240

241+
static int mv88e6xxx_phy_page_get(struct mv88e6xxx_chip *chip, int phy, u8 page)
242+
{
243+
if (!mv88e6xxx_has(chip, MV88E6XXX_FLAG_PHY_PAGE))
244+
return -EOPNOTSUPP;
245+
246+
return mv88e6xxx_phy_write(chip, phy, PHY_PAGE, page);
247+
}
248+
249+
static void mv88e6xxx_phy_page_put(struct mv88e6xxx_chip *chip, int phy)
250+
{
251+
int err;
252+
253+
/* Restore PHY page Copper 0x0 for access via the registered MDIO bus */
254+
err = mv88e6xxx_phy_write(chip, phy, PHY_PAGE, PHY_PAGE_COPPER);
255+
if (unlikely(err)) {
256+
dev_err(chip->dev, "failed to restore PHY %d page Copper (%d)\n",
257+
phy, err);
258+
}
259+
}
260+
261+
static int mv88e6xxx_phy_page_read(struct mv88e6xxx_chip *chip, int phy,
262+
u8 page, int reg, u16 *val)
263+
{
264+
int err;
265+
266+
/* There is no paging for registers 22 */
267+
if (reg == PHY_PAGE)
268+
return -EINVAL;
269+
270+
err = mv88e6xxx_phy_page_get(chip, phy, page);
271+
if (!err) {
272+
err = mv88e6xxx_phy_read(chip, phy, reg, val);
273+
mv88e6xxx_phy_page_put(chip, phy);
274+
}
275+
276+
return err;
277+
}
278+
279+
static int mv88e6xxx_phy_page_write(struct mv88e6xxx_chip *chip, int phy,
280+
u8 page, int reg, u16 val)
281+
{
282+
int err;
283+
284+
/* There is no paging for registers 22 */
285+
if (reg == PHY_PAGE)
286+
return -EINVAL;
287+
288+
err = mv88e6xxx_phy_page_get(chip, phy, page);
289+
if (!err) {
290+
err = mv88e6xxx_phy_write(chip, phy, PHY_PAGE, page);
291+
mv88e6xxx_phy_page_put(chip, phy);
292+
}
293+
294+
return err;
295+
}
296+
297+
static int mv88e6xxx_serdes_read(struct mv88e6xxx_chip *chip, int reg, u16 *val)
298+
{
299+
return mv88e6xxx_phy_page_read(chip, ADDR_SERDES, SERDES_PAGE_FIBER,
300+
reg, val);
301+
}
302+
303+
static int mv88e6xxx_serdes_write(struct mv88e6xxx_chip *chip, int reg, u16 val)
304+
{
305+
return mv88e6xxx_phy_page_write(chip, ADDR_SERDES, SERDES_PAGE_FIBER,
306+
reg, val);
307+
}
308+
241309
static int mv88e6xxx_wait(struct mv88e6xxx_chip *chip, int addr, int reg,
242310
u16 mask)
243311
{
@@ -2408,23 +2476,22 @@ static int mv88e6xxx_switch_reset(struct mv88e6xxx_chip *chip)
24082476
return ret;
24092477
}
24102478

2411-
static int mv88e6xxx_power_on_serdes(struct mv88e6xxx_chip *chip)
2479+
static int mv88e6xxx_serdes_power_on(struct mv88e6xxx_chip *chip)
24122480
{
2413-
int ret;
2481+
u16 val;
2482+
int err;
24142483

2415-
ret = _mv88e6xxx_mdio_page_read(chip, REG_FIBER_SERDES,
2416-
PAGE_FIBER_SERDES, MII_BMCR);
2417-
if (ret < 0)
2418-
return ret;
2484+
/* Clear Power Down bit */
2485+
err = mv88e6xxx_serdes_read(chip, MII_BMCR, &val);
2486+
if (err)
2487+
return err;
24192488

2420-
if (ret & BMCR_PDOWN) {
2421-
ret &= ~BMCR_PDOWN;
2422-
ret = _mv88e6xxx_mdio_page_write(chip, REG_FIBER_SERDES,
2423-
PAGE_FIBER_SERDES, MII_BMCR,
2424-
ret);
2489+
if (val & BMCR_PDOWN) {
2490+
val &= ~BMCR_PDOWN;
2491+
err = mv88e6xxx_serdes_write(chip, MII_BMCR, val);
24252492
}
24262493

2427-
return ret;
2494+
return err;
24282495
}
24292496

24302497
static int mv88e6xxx_port_read(struct mv88e6xxx_chip *chip, int port,
@@ -2547,15 +2614,15 @@ static int mv88e6xxx_setup_port(struct mv88e6xxx_chip *chip, int port)
25472614
/* If this port is connected to a SerDes, make sure the SerDes is not
25482615
* powered down.
25492616
*/
2550-
if (mv88e6xxx_6352_family(chip)) {
2617+
if (mv88e6xxx_has(chip, MV88E6XXX_FLAGS_SERDES)) {
25512618
ret = _mv88e6xxx_reg_read(chip, REG_PORT(port), PORT_STATUS);
25522619
if (ret < 0)
25532620
return ret;
25542621
ret &= PORT_STATUS_CMODE_MASK;
25552622
if ((ret == PORT_STATUS_CMODE_100BASE_X) ||
25562623
(ret == PORT_STATUS_CMODE_1000BASE_X) ||
25572624
(ret == PORT_STATUS_CMODE_SGMII)) {
2558-
ret = mv88e6xxx_power_on_serdes(chip);
2625+
ret = mv88e6xxx_serdes_power_on(chip);
25592626
if (ret < 0)
25602627
return ret;
25612628
}

drivers/net/dsa/mv88e6xxx/mv88e6xxx.h

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,12 @@
3030
#define SMI_CMD_OP_45_READ_DATA_INC ((3 << 10) | SMI_CMD_BUSY)
3131
#define SMI_DATA 0x01
3232

33-
/* Fiber/SERDES Registers are located at SMI address F, page 1 */
34-
#define REG_FIBER_SERDES 0x0f
35-
#define PAGE_FIBER_SERDES 0x01
33+
/* PHY Registers */
34+
#define PHY_PAGE 0x16
35+
#define PHY_PAGE_COPPER 0x00
36+
37+
#define ADDR_SERDES 0x0f
38+
#define SERDES_PAGE_FIBER 0x01
3639

3740
#define REG_PORT(p) (0x10 + (p))
3841
#define PORT_STATUS 0x00
@@ -394,6 +397,14 @@ enum mv88e6xxx_cap {
394397
MV88E6XXX_CAP_SMI_CMD, /* (0x00) SMI Command */
395398
MV88E6XXX_CAP_SMI_DATA, /* (0x01) SMI Data */
396399

400+
/* PHY Registers.
401+
*/
402+
MV88E6XXX_CAP_PHY_PAGE, /* (0x16) Page Register */
403+
404+
/* Fiber/SERDES Registers (SMI address F).
405+
*/
406+
MV88E6XXX_CAP_SERDES,
407+
397408
/* Switch Global 2 Registers.
398409
* The device contains a second set of global 16-bit registers.
399410
*/
@@ -441,6 +452,10 @@ enum mv88e6xxx_cap {
441452
#define MV88E6XXX_FLAG_SMI_CMD BIT(MV88E6XXX_CAP_SMI_CMD)
442453
#define MV88E6XXX_FLAG_SMI_DATA BIT(MV88E6XXX_CAP_SMI_DATA)
443454

455+
#define MV88E6XXX_FLAG_PHY_PAGE BIT(MV88E6XXX_CAP_PHY_PAGE)
456+
457+
#define MV88E6XXX_FLAG_SERDES BIT(MV88E6XXX_CAP_SERDES)
458+
444459
#define MV88E6XXX_FLAG_GLOBAL2 BIT(MV88E6XXX_CAP_GLOBAL2)
445460
#define MV88E6XXX_FLAG_G2_MGMT_EN_2X BIT(MV88E6XXX_CAP_G2_MGMT_EN_2X)
446461
#define MV88E6XXX_FLAG_G2_MGMT_EN_0X BIT(MV88E6XXX_CAP_G2_MGMT_EN_0X)
@@ -482,6 +497,11 @@ enum mv88e6xxx_cap {
482497
(MV88E6XXX_FLAG_G2_PVT_ADDR | \
483498
MV88E6XXX_FLAG_G2_PVT_DATA)
484499

500+
/* Fiber/SERDES Registers at SMI address F, page 1 */
501+
#define MV88E6XXX_FLAGS_SERDES \
502+
(MV88E6XXX_FLAG_PHY_PAGE | \
503+
MV88E6XXX_FLAG_SERDES)
504+
485505
/* Indirect PHY access via Global2 SMI PHY registers */
486506
#define MV88E6XXX_FLAGS_SMI_PHY \
487507
(MV88E6XXX_FLAG_G2_SMI_PHY_CMD |\
@@ -574,6 +594,7 @@ enum mv88e6xxx_cap {
574594
MV88E6XXX_FLAGS_IRL | \
575595
MV88E6XXX_FLAGS_MULTI_CHIP | \
576596
MV88E6XXX_FLAGS_PVT | \
597+
MV88E6XXX_FLAGS_SERDES | \
577598
MV88E6XXX_FLAGS_SMI_PHY)
578599

579600
struct mv88e6xxx_info {

0 commit comments

Comments
 (0)