Skip to content

Commit ab0cde3

Browse files
Gregor Herburgerdavem330
authored andcommitted
net: phy: marvell-88q2xxx: add support for Rev B1 and B2
Different revisions of the Marvell 88q2xxx phy needs different init sequences. Add init sequence for Rev B1 and Rev B2. Rev B2 init sequence skips one register write. Tested-by: Dimitri Fedrau <[email protected]> Signed-off-by: Gregor Herburger <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 2e82a58 commit ab0cde3

File tree

1 file changed

+103
-16
lines changed

1 file changed

+103
-16
lines changed

drivers/net/phy/marvell-88q2xxx.c

Lines changed: 103 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212
#include <linux/hwmon.h>
1313

1414
#define PHY_ID_88Q2220_REVB0 (MARVELL_PHY_ID_88Q2220 | 0x1)
15+
#define PHY_ID_88Q2220_REVB1 (MARVELL_PHY_ID_88Q2220 | 0x2)
16+
#define PHY_ID_88Q2220_REVB2 (MARVELL_PHY_ID_88Q2220 | 0x3)
1517

1618
#define MDIO_MMD_AN_MV_STAT 32769
1719
#define MDIO_MMD_AN_MV_STAT_ANEG 0x0100
@@ -129,6 +131,49 @@ static const struct mmd_val mv88q222x_revb0_init_seq1[] = {
129131
{ MDIO_MMD_PCS, 0xfe05, 0x755c },
130132
};
131133

134+
static const struct mmd_val mv88q222x_revb1_init_seq0[] = {
135+
{ MDIO_MMD_PCS, 0xffe4, 0x0007 },
136+
{ MDIO_MMD_AN, MDIO_AN_T1_CTRL, 0x0 },
137+
{ MDIO_MMD_PCS, 0xffe3, 0x7000 },
138+
{ MDIO_MMD_PMAPMD, MDIO_CTRL1, 0x0840 },
139+
};
140+
141+
static const struct mmd_val mv88q222x_revb2_init_seq0[] = {
142+
{ MDIO_MMD_PCS, 0xffe4, 0x0007 },
143+
{ MDIO_MMD_AN, MDIO_AN_T1_CTRL, 0x0 },
144+
{ MDIO_MMD_PMAPMD, MDIO_CTRL1, 0x0840 },
145+
};
146+
147+
static const struct mmd_val mv88q222x_revb1_revb2_init_seq1[] = {
148+
{ MDIO_MMD_PCS, 0xfe07, 0x125a },
149+
{ MDIO_MMD_PCS, 0xfe09, 0x1288 },
150+
{ MDIO_MMD_PCS, 0xfe08, 0x2588 },
151+
{ MDIO_MMD_PCS, 0xfe72, 0x042c },
152+
{ MDIO_MMD_PCS, 0xffe4, 0x0071 },
153+
{ MDIO_MMD_PCS, 0xffe4, 0x0001 },
154+
{ MDIO_MMD_PCS, 0xfe1b, 0x0048 },
155+
{ MDIO_MMD_PMAPMD, 0x0000, 0x0000 },
156+
{ MDIO_MMD_PCS, 0x0000, 0x0000 },
157+
{ MDIO_MMD_PCS, 0xffdb, 0xfc10 },
158+
{ MDIO_MMD_PCS, 0xfe1b, 0x58 },
159+
{ MDIO_MMD_PCS, 0xfcad, 0x030c },
160+
{ MDIO_MMD_PCS, 0x8032, 0x6001 },
161+
{ MDIO_MMD_PCS, 0xfdff, 0x05a5 },
162+
{ MDIO_MMD_PCS, 0xfdec, 0xdbaf },
163+
{ MDIO_MMD_PCS, 0xfcab, 0x1054 },
164+
{ MDIO_MMD_PCS, 0xfcac, 0x1483 },
165+
{ MDIO_MMD_PCS, 0x8033, 0xc801 },
166+
{ MDIO_MMD_AN, 0x8032, 0x2020 },
167+
{ MDIO_MMD_AN, 0x8031, 0xa28 },
168+
{ MDIO_MMD_AN, 0x8031, 0xc28 },
169+
{ MDIO_MMD_PCS, 0xfbba, 0x0cb2 },
170+
{ MDIO_MMD_PCS, 0xfbbb, 0x0c4a },
171+
{ MDIO_MMD_PCS, 0xfe5f, 0xe8 },
172+
{ MDIO_MMD_PCS, 0xfe05, 0x755c },
173+
{ MDIO_MMD_PCS, 0xfa20, 0x002a },
174+
{ MDIO_MMD_PCS, 0xfe11, 0x1105 },
175+
};
176+
132177
static int mv88q2xxx_soft_reset(struct phy_device *phydev)
133178
{
134179
int ret;
@@ -687,31 +732,72 @@ static int mv88q222x_soft_reset(struct phy_device *phydev)
687732
return 0;
688733
}
689734

690-
static int mv88q222x_revb0_config_init(struct phy_device *phydev)
735+
static int mv88q222x_write_mmd_vals(struct phy_device *phydev,
736+
const struct mmd_val *vals, size_t len)
691737
{
692-
int ret, i;
738+
int ret;
693739

694-
for (i = 0; i < ARRAY_SIZE(mv88q222x_revb0_init_seq0); i++) {
695-
ret = phy_write_mmd(phydev, mv88q222x_revb0_init_seq0[i].devad,
696-
mv88q222x_revb0_init_seq0[i].regnum,
697-
mv88q222x_revb0_init_seq0[i].val);
740+
for (; len; vals++, len--) {
741+
ret = phy_write_mmd(phydev, vals->devad, vals->regnum,
742+
vals->val);
698743
if (ret < 0)
699744
return ret;
700745
}
701746

747+
return 0;
748+
}
749+
750+
static int mv88q222x_revb0_config_init(struct phy_device *phydev)
751+
{
752+
int ret;
753+
754+
ret = mv88q222x_write_mmd_vals(phydev, mv88q222x_revb0_init_seq0,
755+
ARRAY_SIZE(mv88q222x_revb0_init_seq0));
756+
if (ret < 0)
757+
return ret;
758+
702759
usleep_range(5000, 10000);
703760

704-
for (i = 0; i < ARRAY_SIZE(mv88q222x_revb0_init_seq1); i++) {
705-
ret = phy_write_mmd(phydev, mv88q222x_revb0_init_seq1[i].devad,
706-
mv88q222x_revb0_init_seq1[i].regnum,
707-
mv88q222x_revb0_init_seq1[i].val);
708-
if (ret < 0)
709-
return ret;
710-
}
761+
ret = mv88q222x_write_mmd_vals(phydev, mv88q222x_revb0_init_seq1,
762+
ARRAY_SIZE(mv88q222x_revb0_init_seq1));
763+
if (ret < 0)
764+
return ret;
765+
766+
return mv88q2xxx_config_init(phydev);
767+
}
768+
769+
static int mv88q222x_revb1_revb2_config_init(struct phy_device *phydev)
770+
{
771+
bool is_rev_b1 = phydev->c45_ids.device_ids[MDIO_MMD_PMAPMD] == PHY_ID_88Q2220_REVB1;
772+
int ret;
773+
774+
if (is_rev_b1)
775+
ret = mv88q222x_write_mmd_vals(phydev, mv88q222x_revb1_init_seq0,
776+
ARRAY_SIZE(mv88q222x_revb1_init_seq0));
777+
else
778+
ret = mv88q222x_write_mmd_vals(phydev, mv88q222x_revb2_init_seq0,
779+
ARRAY_SIZE(mv88q222x_revb2_init_seq0));
780+
if (ret < 0)
781+
return ret;
782+
783+
usleep_range(3000, 5000);
784+
785+
ret = mv88q222x_write_mmd_vals(phydev, mv88q222x_revb1_revb2_init_seq1,
786+
ARRAY_SIZE(mv88q222x_revb1_revb2_init_seq1));
787+
if (ret < 0)
788+
return ret;
711789

712790
return mv88q2xxx_config_init(phydev);
713791
}
714792

793+
static int mv88q222x_config_init(struct phy_device *phydev)
794+
{
795+
if (phydev->c45_ids.device_ids[MDIO_MMD_PMAPMD] == PHY_ID_88Q2220_REVB0)
796+
return mv88q222x_revb0_config_init(phydev);
797+
else
798+
return mv88q222x_revb1_revb2_config_init(phydev);
799+
}
800+
715801
static int mv88q222x_cable_test_start(struct phy_device *phydev)
716802
{
717803
int ret;
@@ -810,14 +896,15 @@ static struct phy_driver mv88q2xxx_driver[] = {
810896
.get_sqi_max = mv88q2xxx_get_sqi_max,
811897
},
812898
{
813-
PHY_ID_MATCH_EXACT(PHY_ID_88Q2220_REVB0),
899+
.phy_id = MARVELL_PHY_ID_88Q2220,
900+
.phy_id_mask = MARVELL_PHY_ID_MASK,
814901
.name = "mv88q2220",
815902
.flags = PHY_POLL_CABLE_TEST,
816903
.probe = mv88q2xxx_probe,
817904
.get_features = mv88q2xxx_get_features,
818905
.config_aneg = mv88q2xxx_config_aneg,
819906
.aneg_done = genphy_c45_aneg_done,
820-
.config_init = mv88q222x_revb0_config_init,
907+
.config_init = mv88q222x_config_init,
821908
.read_status = mv88q2xxx_read_status,
822909
.soft_reset = mv88q222x_soft_reset,
823910
.config_intr = mv88q2xxx_config_intr,
@@ -836,7 +923,7 @@ module_phy_driver(mv88q2xxx_driver);
836923

837924
static struct mdio_device_id __maybe_unused mv88q2xxx_tbl[] = {
838925
{ MARVELL_PHY_ID_88Q2110, MARVELL_PHY_ID_MASK },
839-
{ PHY_ID_MATCH_EXACT(PHY_ID_88Q2220_REVB0), },
926+
{ MARVELL_PHY_ID_88Q2220, MARVELL_PHY_ID_MASK },
840927
{ /*sentinel*/ }
841928
};
842929
MODULE_DEVICE_TABLE(mdio, mv88q2xxx_tbl);

0 commit comments

Comments
 (0)