1 // SPDX-License-Identifier: GPL-2.0+
4 * Dirk Eibach, Guntermann & Drunck GmbH, dirk.eibach@gdsys.cc
16 MIICMD_WAIT_FOR_VALUE,
28 * verify we are talking to a 88e1518
30 struct mii_setupcmd verify_88e1518[] = {
31 { MIICMD_SET, 22, 0x0000 },
32 { MIICMD_VERIFY_VALUE, 2, 0x0141, 0xffff },
33 { MIICMD_VERIFY_VALUE, 3, 0x0dd0, 0xfff0 },
37 * workaround for erratum mentioned in 88E1518 release notes
39 struct mii_setupcmd fixup_88e1518[] = {
40 { MIICMD_SET, 22, 0x00ff },
41 { MIICMD_SET, 17, 0x214b },
42 { MIICMD_SET, 16, 0x2144 },
43 { MIICMD_SET, 17, 0x0c28 },
44 { MIICMD_SET, 16, 0x2146 },
45 { MIICMD_SET, 17, 0xb233 },
46 { MIICMD_SET, 16, 0x214d },
47 { MIICMD_SET, 17, 0xcc0c },
48 { MIICMD_SET, 16, 0x2159 },
49 { MIICMD_SET, 22, 0x0000 },
53 * default initialization:
54 * - set RGMII receive timing to "receive clock transition when data stable"
55 * - set RGMII transmit timing to "transmit clock internally delayed"
56 * - set RGMII output impedance target to 78,8 Ohm
57 * - run output impedance calibration
58 * - set autonegotiation advertise to 1000FD only
60 struct mii_setupcmd default_88e1518[] = {
61 { MIICMD_SET, 22, 0x0002 },
62 { MIICMD_MODIFY, 21, 0x0030, 0x0030 },
63 { MIICMD_MODIFY, 25, 0x0000, 0x0003 },
64 { MIICMD_MODIFY, 24, 0x8000, 0x8000 },
65 { MIICMD_WAIT_FOR_VALUE, 24, 0x4000, 0x4000, 2000 },
66 { MIICMD_SET, 22, 0x0000 },
67 { MIICMD_MODIFY, 4, 0x0000, 0x01e0 },
68 { MIICMD_MODIFY, 9, 0x0200, 0x0300 },
72 * turn off CLK125 for PHY daughterboard
74 struct mii_setupcmd ch1fix_88e1518[] = {
75 { MIICMD_SET, 22, 0x0002 },
76 { MIICMD_MODIFY, 16, 0x0006, 0x0006 },
77 { MIICMD_SET, 22, 0x0000 },
81 * perform copper software reset
83 struct mii_setupcmd swreset_88e1518[] = {
84 { MIICMD_SET, 22, 0x0000 },
85 { MIICMD_MODIFY, 0, 0x8000, 0x8000 },
86 { MIICMD_WAIT_FOR_VALUE, 0, 0x0000, 0x8000, 2000 },
90 * special one for 88E1514:
91 * Force SGMII to Copper mode
93 struct mii_setupcmd mii_to_copper_88e1514[] = {
94 { MIICMD_SET, 22, 0x0012 },
95 { MIICMD_MODIFY, 20, 0x0001, 0x0007 },
96 { MIICMD_MODIFY, 20, 0x8000, 0x8000 },
97 { MIICMD_SET, 22, 0x0000 },
101 * turn off SGMII auto-negotiation
103 struct mii_setupcmd sgmii_autoneg_off_88e1518[] = {
104 { MIICMD_SET, 22, 0x0001 },
105 { MIICMD_MODIFY, 0, 0x0000, 0x1000 },
106 { MIICMD_MODIFY, 0, 0x8000, 0x8000 },
107 { MIICMD_SET, 22, 0x0000 },
111 * invert LED2 polarity
113 struct mii_setupcmd invert_led2_88e1514[] = {
114 { MIICMD_SET, 22, 0x0003 },
115 { MIICMD_MODIFY, 17, 0x0030, 0x0010 },
116 { MIICMD_SET, 22, 0x0000 },
119 static int process_setupcmd(const char *bus, unsigned char addr,
120 struct mii_setupcmd *setupcmd)
123 u8 reg = setupcmd->reg;
124 u16 data = setupcmd->data;
125 u16 mask = setupcmd->mask;
126 u32 timeout = setupcmd->timeout;
130 debug("mii %s:%u reg %2u ", bus, addr, reg);
132 switch (setupcmd->token) {
134 res = miiphy_read(bus, addr, reg, &orig_data);
137 debug("is %04x. (value %04x mask %04x) ", orig_data, data,
139 data = (orig_data & ~mask) | (data & mask);
142 debug("=> %04x\n", data);
143 res = miiphy_write(bus, addr, reg, data);
145 case MIICMD_VERIFY_VALUE:
146 res = miiphy_read(bus, addr, reg, &orig_data);
149 if ((orig_data & mask) != (data & mask))
151 debug("(value %04x mask %04x) == %04x? %s\n", data, mask,
152 orig_data, res ? "FAIL" : "PASS");
154 case MIICMD_WAIT_FOR_VALUE:
156 start = get_timer(0);
157 while ((res != 0) && (get_timer(start) < timeout)) {
158 res = miiphy_read(bus, addr, reg, &orig_data);
161 if ((orig_data & mask) != (data & mask))
164 debug("(value %04x mask %04x) == %04x? %s after %lu ms\n", data,
165 mask, orig_data, res ? "FAIL" : "PASS",
176 static int process_setup(const char *bus, unsigned char addr,
177 struct mii_setupcmd *setupcmd, unsigned int count)
182 for (k = 0; k < count; ++k) {
183 res = process_setupcmd(bus, addr, &setupcmd[k]);
185 printf("mii cmd %u on bus %s addr %u failed, aborting setup\n",
186 setupcmd[k].token, bus, addr);
194 int setup_88e1518(const char *bus, unsigned char addr)
198 res = process_setup(bus, addr,
199 verify_88e1518, ARRAY_SIZE(verify_88e1518));
203 res = process_setup(bus, addr,
204 fixup_88e1518, ARRAY_SIZE(fixup_88e1518));
208 res = process_setup(bus, addr,
209 default_88e1518, ARRAY_SIZE(default_88e1518));
214 res = process_setup(bus, addr,
215 ch1fix_88e1518, ARRAY_SIZE(ch1fix_88e1518));
220 res = process_setup(bus, addr,
221 swreset_88e1518, ARRAY_SIZE(swreset_88e1518));
228 int setup_88e1514(const char *bus, unsigned char addr)
232 res = process_setup(bus, addr,
233 verify_88e1518, ARRAY_SIZE(verify_88e1518));
237 res = process_setup(bus, addr,
238 fixup_88e1518, ARRAY_SIZE(fixup_88e1518));
242 res = process_setup(bus, addr,
243 mii_to_copper_88e1514,
244 ARRAY_SIZE(mii_to_copper_88e1514));
248 res = process_setup(bus, addr,
249 sgmii_autoneg_off_88e1518,
250 ARRAY_SIZE(sgmii_autoneg_off_88e1518));
254 res = process_setup(bus, addr,
256 ARRAY_SIZE(invert_led2_88e1514));
260 res = process_setup(bus, addr,
261 default_88e1518, ARRAY_SIZE(default_88e1518));
266 res = process_setup(bus, addr,
267 ch1fix_88e1518, ARRAY_SIZE(ch1fix_88e1518));
272 res = process_setup(bus, addr,
273 swreset_88e1518, ARRAY_SIZE(swreset_88e1518));