Skip to content

Commit 6d91782

Browse files
lunndavem330
authored andcommitted
net: dsa: mv88e6xxx: Refactor mv88e6352 SERDES code into an op
The mv88e6390 family has a different SERDES implementation. Refactor the mv88e6352 code into an ops function, so we can later add the mv88e6390 code. Signed-off-by: Andrew Lunn <andrew@lunn.ch> Reviewed-by: Vivien Didelot <vivien.didelot@savoirfairelinux.com> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent 10fa5bf commit 6d91782

File tree

5 files changed

+122
-48
lines changed

5 files changed

+122
-48
lines changed

drivers/net/dsa/mv88e6xxx/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,4 @@ mv88e6xxx-objs += global1_vtu.o
66
mv88e6xxx-$(CONFIG_NET_DSA_MV88E6XXX_GLOBAL2) += global2.o
77
mv88e6xxx-objs += phy.o
88
mv88e6xxx-objs += port.o
9+
mv88e6xxx-objs += serdes.o

drivers/net/dsa/mv88e6xxx/chip.c

Lines changed: 19 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
#include "global2.h"
3939
#include "phy.h"
4040
#include "port.h"
41+
#include "serdes.h"
4142

4243
static void assert_reg_lock(struct mv88e6xxx_chip *chip)
4344
{
@@ -234,18 +235,6 @@ struct mii_bus *mv88e6xxx_default_mdio_bus(struct mv88e6xxx_chip *chip)
234235
return mdio_bus->bus;
235236
}
236237

237-
static int mv88e6xxx_serdes_read(struct mv88e6xxx_chip *chip, int reg, u16 *val)
238-
{
239-
return mv88e6xxx_phy_page_read(chip, ADDR_SERDES, SERDES_PAGE_FIBER,
240-
reg, val);
241-
}
242-
243-
static int mv88e6xxx_serdes_write(struct mv88e6xxx_chip *chip, int reg, u16 val)
244-
{
245-
return mv88e6xxx_phy_page_write(chip, ADDR_SERDES, SERDES_PAGE_FIBER,
246-
reg, val);
247-
}
248-
249238
static void mv88e6xxx_g1_irq_mask(struct irq_data *d)
250239
{
251240
struct mv88e6xxx_chip *chip = irq_data_get_irq_chip_data(d);
@@ -1733,24 +1722,6 @@ static int mv88e6xxx_switch_reset(struct mv88e6xxx_chip *chip)
17331722
return mv88e6xxx_software_reset(chip);
17341723
}
17351724

1736-
static int mv88e6xxx_serdes_power_on(struct mv88e6xxx_chip *chip)
1737-
{
1738-
u16 val;
1739-
int err;
1740-
1741-
/* Clear Power Down bit */
1742-
err = mv88e6xxx_serdes_read(chip, MII_BMCR, &val);
1743-
if (err)
1744-
return err;
1745-
1746-
if (val & BMCR_PDOWN) {
1747-
val &= ~BMCR_PDOWN;
1748-
err = mv88e6xxx_serdes_write(chip, MII_BMCR, val);
1749-
}
1750-
1751-
return err;
1752-
}
1753-
17541725
static int mv88e6xxx_set_port_mode(struct mv88e6xxx_chip *chip, int port,
17551726
enum mv88e6xxx_frame_mode frame, u16 egress,
17561727
u16 etype)
@@ -1832,6 +1803,15 @@ static int mv88e6xxx_setup_egress_floods(struct mv88e6xxx_chip *chip, int port)
18321803
return 0;
18331804
}
18341805

1806+
static int mv88e6xxx_serdes_power(struct mv88e6xxx_chip *chip, int port,
1807+
bool on)
1808+
{
1809+
if (chip->info->ops->serdes_power)
1810+
return chip->info->ops->serdes_power(chip, port, on);
1811+
1812+
return 0;
1813+
}
1814+
18351815
static int mv88e6xxx_setup_port(struct mv88e6xxx_chip *chip, int port)
18361816
{
18371817
struct dsa_switch *ds = chip->ds;
@@ -1882,22 +1862,12 @@ static int mv88e6xxx_setup_port(struct mv88e6xxx_chip *chip, int port)
18821862
if (err)
18831863
return err;
18841864

1885-
/* If this port is connected to a SerDes, make sure the SerDes is not
1886-
* powered down.
1865+
/* If this port is connected to a SerDes, make sure the SerDes is
1866+
* powered up.
18871867
*/
1888-
if (mv88e6xxx_has(chip, MV88E6XXX_FLAGS_SERDES)) {
1889-
err = mv88e6xxx_port_read(chip, port, PORT_STATUS, &reg);
1890-
if (err)
1891-
return err;
1892-
reg &= PORT_STATUS_CMODE_MASK;
1893-
if ((reg == PORT_STATUS_CMODE_100BASE_X) ||
1894-
(reg == PORT_STATUS_CMODE_1000BASE_X) ||
1895-
(reg == PORT_STATUS_CMODE_SGMII)) {
1896-
err = mv88e6xxx_serdes_power_on(chip);
1897-
if (err < 0)
1898-
return err;
1899-
}
1900-
}
1868+
err = mv88e6xxx_serdes_power(chip, port, true);
1869+
if (err)
1870+
return err;
19011871

19021872
/* Port Control 2: don't force a good FCS, set the maximum frame size to
19031873
* 10240 bytes, disable 802.1q tags checking, don't discard tagged or
@@ -2662,6 +2632,7 @@ static const struct mv88e6xxx_ops mv88e6172_ops = {
26622632
.reset = mv88e6352_g1_reset,
26632633
.vtu_getnext = mv88e6352_g1_vtu_getnext,
26642634
.vtu_loadpurge = mv88e6352_g1_vtu_loadpurge,
2635+
.serdes_power = mv88e6352_serdes_power,
26652636
};
26662637

26672638
static const struct mv88e6xxx_ops mv88e6175_ops = {
@@ -2726,6 +2697,7 @@ static const struct mv88e6xxx_ops mv88e6176_ops = {
27262697
.reset = mv88e6352_g1_reset,
27272698
.vtu_getnext = mv88e6352_g1_vtu_getnext,
27282699
.vtu_loadpurge = mv88e6352_g1_vtu_loadpurge,
2700+
.serdes_power = mv88e6352_serdes_power,
27292701
};
27302702

27312703
static const struct mv88e6xxx_ops mv88e6185_ops = {
@@ -2882,6 +2854,7 @@ static const struct mv88e6xxx_ops mv88e6240_ops = {
28822854
.reset = mv88e6352_g1_reset,
28832855
.vtu_getnext = mv88e6352_g1_vtu_getnext,
28842856
.vtu_loadpurge = mv88e6352_g1_vtu_loadpurge,
2857+
.serdes_power = mv88e6352_serdes_power,
28852858
};
28862859

28872860
static const struct mv88e6xxx_ops mv88e6290_ops = {
@@ -3104,6 +3077,7 @@ static const struct mv88e6xxx_ops mv88e6352_ops = {
31043077
.reset = mv88e6352_g1_reset,
31053078
.vtu_getnext = mv88e6352_g1_vtu_getnext,
31063079
.vtu_loadpurge = mv88e6352_g1_vtu_loadpurge,
3080+
.serdes_power = mv88e6352_serdes_power,
31073081
};
31083082

31093083
static const struct mv88e6xxx_ops mv88e6390_ops = {

drivers/net/dsa/mv88e6xxx/mv88e6xxx.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,9 +37,6 @@
3737
#define PHY_PAGE 0x16
3838
#define PHY_PAGE_COPPER 0x00
3939

40-
#define ADDR_SERDES 0x0f
41-
#define SERDES_PAGE_FIBER 0x01
42-
4340
#define PORT_STATUS 0x00
4441
#define PORT_STATUS_PAUSE_EN BIT(15)
4542
#define PORT_STATUS_MY_PAUSE BIT(14)
@@ -884,6 +881,9 @@ struct mv88e6xxx_ops {
884881
/* Can be either in g1 or g2, so don't use a prefix */
885882
int (*mgmt_rsvd2cpu)(struct mv88e6xxx_chip *chip);
886883

884+
/* Power on/off a SERDES interface */
885+
int (*serdes_power)(struct mv88e6xxx_chip *chip, int port, bool on);
886+
887887
/* VLAN Translation Unit operations */
888888
int (*vtu_getnext)(struct mv88e6xxx_chip *chip,
889889
struct mv88e6xxx_vtu_entry *entry);

drivers/net/dsa/mv88e6xxx/serdes.c

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
/*
2+
* Marvell 88E6xxx SERDES manipulation, via SMI bus
3+
*
4+
* Copyright (c) 2008 Marvell Semiconductor
5+
*
6+
* Copyright (c) 2017 Andrew Lunn <andrew@lunn.ch>
7+
*
8+
* This program is free software; you can redistribute it and/or modify
9+
* it under the terms of the GNU General Public License as published by
10+
* the Free Software Foundation; either version 2 of the License, or
11+
* (at your option) any later version.
12+
*/
13+
14+
#include <linux/mii.h>
15+
16+
#include "mv88e6xxx.h"
17+
#include "phy.h"
18+
#include "port.h"
19+
#include "serdes.h"
20+
21+
static int mv88e6352_serdes_read(struct mv88e6xxx_chip *chip, int reg,
22+
u16 *val)
23+
{
24+
return mv88e6xxx_phy_page_read(chip, MV88E6352_ADDR_SERDES,
25+
MV88E6352_SERDES_PAGE_FIBER,
26+
reg, val);
27+
}
28+
29+
static int mv88e6352_serdes_write(struct mv88e6xxx_chip *chip, int reg,
30+
u16 val)
31+
{
32+
return mv88e6xxx_phy_page_write(chip, MV88E6352_ADDR_SERDES,
33+
MV88E6352_SERDES_PAGE_FIBER,
34+
reg, val);
35+
}
36+
37+
static int mv88e6352_serdes_power_set(struct mv88e6xxx_chip *chip, bool on)
38+
{
39+
u16 val, new_val;
40+
int err;
41+
42+
err = mv88e6352_serdes_read(chip, MII_BMCR, &val);
43+
if (err)
44+
return err;
45+
46+
if (on)
47+
new_val = val & ~BMCR_PDOWN;
48+
else
49+
new_val = val | BMCR_PDOWN;
50+
51+
if (val != new_val)
52+
err = mv88e6352_serdes_write(chip, MII_BMCR, new_val);
53+
54+
return err;
55+
}
56+
57+
int mv88e6352_serdes_power(struct mv88e6xxx_chip *chip, int port, bool on)
58+
{
59+
int err;
60+
u8 cmode;
61+
62+
err = mv88e6xxx_port_get_cmode(chip, port, &cmode);
63+
if (err)
64+
return err;
65+
66+
if ((cmode == PORT_STATUS_CMODE_100BASE_X) ||
67+
(cmode == PORT_STATUS_CMODE_1000BASE_X) ||
68+
(cmode == PORT_STATUS_CMODE_SGMII)) {
69+
err = mv88e6352_serdes_power_set(chip, on);
70+
if (err < 0)
71+
return err;
72+
}
73+
74+
return 0;
75+
}

drivers/net/dsa/mv88e6xxx/serdes.h

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
/*
2+
* Marvell 88E6xxx SERDES manipulation, via SMI bus
3+
*
4+
* Copyright (c) 2008 Marvell Semiconductor
5+
*
6+
* Copyright (c) 2016 Andrew Lunn <andrew@lunn.ch>
7+
*
8+
* This program is free software; you can redistribute it and/or modify
9+
* it under the terms of the GNU General Public License as published by
10+
* the Free Software Foundation; either version 2 of the License, or
11+
* (at your option) any later version.
12+
*/
13+
14+
#ifndef _MV88E6XXX_SERDES_H
15+
#define _MV88E6XXX_SERDES_H
16+
17+
#include "mv88e6xxx.h"
18+
19+
#define MV88E6352_ADDR_SERDES 0x0f
20+
#define MV88E6352_SERDES_PAGE_FIBER 0x01
21+
22+
int mv88e6352_serdes_power(struct mv88e6xxx_chip *chip, int port, bool on);
23+
24+
#endif

0 commit comments

Comments
 (0)