blob: d033f7245954512d0d8ceb824eb591ca5905555a [file] [log] [blame]
xjb04a4022021-11-25 15:01:52 +08001// SPDX-License-Identifier: GPL-2.0
2/*
3 * Copyright (c) 2019 MediaTek Inc.
4 */
5#include <linux/module.h>
6#include <linux/phy.h>
7#include <linux/of.h>
xf.li2230aac2022-09-09 00:23:23 -07008//xf.li 2022/9/9 modify for LPSD mode start
9#include <linux/of_gpio.h>
10#include <linux/gpio/consumer.h>
11//xf.li 2022/9/9 modify for LPSD mode end
ll3e22ca62022-06-22 10:50:31 +080012#include <linux/delay.h>
13
xjb04a4022021-11-25 15:01:52 +080014
lxf359d1312023-07-28 04:04:02 -070015#define PHY_ID_88Q2220_B0 0x002b0b21
16#define PHY_ID_88Q2220_B1 0x002b0b22
xjb04a4022021-11-25 15:01:52 +080017
18#define Q2110_PMA_PMD_CTRL (MII_ADDR_C45 | 0x10000)
19/* 1 = PMA/PMD reset, 0 = Normal */
20#define Q2110_PMA_PMD_RST BIT(15)
21
22#define Q2110_T1_PMA_PMD_CTRL (MII_ADDR_C45 | 0x10834)
23/* 1 = PHY as master, 0 = PHY as slave */
24#define Q2110_T1_MASTER_SLAVE_CFG BIT(14)
25/* 0 = 100BASE-T1, 1 = 1000BASE-T1 */
26#define Q2110_T1_LINK_TYPE BIT(0)
27
28#define Q2110_RST_CTRL (MII_ADDR_C45 | 0x038000)
29/* software reset of T-unit */
30#define Q2110_RGMII_SW_RESET BIT(15)
31
32#define Q2110_PCS_CTRL (MII_ADDR_C45 | 0x030900)
33#define Q2110_LOOPBACK BIT(14)
34
35#define Q2110_T1_AN_STATUS (MII_ADDR_C45 | 0x070201)
36/* 1 = Link Up, 0 = Link Down */
37#define Q2110_T1_LINK_STATUS BIT(2)
38
c.chenbaa06e92022-04-17 23:27:27 -070039#define Q2110_COM_PORT_CTRL (MII_ADDR_C45 | 0x4A001)
xjb04a4022021-11-25 15:01:52 +080040/* Add delay on TX_CLK */
41#define Q2110_RGMII_TX_TIMING_CTRL BIT(15)
42/* Add delay on RX_CLK */
43#define Q2110_RGMII_RX_TIMING_CTRL BIT(14)
44
xf.li9d095322023-02-07 18:04:49 -080045/* NAD_WAKEUP_PHY1 : GPIO7 */
46#define NAD_WAKEUP_PHY1 275
47/* NAD_RESET_PHY1 : GPIO26 */
48#define NAD_RESET_PHY1 294
xf.li742b5c02023-04-01 02:05:52 -070049/* PHY_POWER_SUPPLY : GPIO178 */
50#define PHY_POWER_SUPPLY 446
xf.li9d095322023-02-07 18:04:49 -080051
52#define Q2220_LPSD_CTRL_1 (MII_ADDR_C45 | 0x038021)
53#define Q2220_LPSD_DISABLE_REMOTE_WAKE_UP BIT(15) | BIT(11)
54#define Q2220_LPSD_STATUS (MII_ADDR_C45 | 0x038020)
55#define Q2220_LPSD_POWER_DOWN BIT(0)
56
xf.liec75fdd2022-11-09 18:24:10 -080057int if_suspend = 0;
58
xjb04a4022021-11-25 15:01:52 +080059/* Set and/or override some configuration registers based on the
60 * marvell,88q2110 property stored in the of_node for the phydev.
61 * marvell,88q2110 = <speed master>,...;
62 * speed: 1000Mbps or 100Mbps.
63 * master: 1-master, 0-slave.
64 */
65static int q2110_dts_init(struct phy_device *phydev)
66{
67 const __be32 *paddr;
68 u32 speed;
69 u32 master;
70 int val, len;
71
72 if (!phydev->mdio.dev.of_node)
73 return 0;
74
75 paddr = of_get_property(phydev->mdio.dev.of_node,
c.chenbaa06e92022-04-17 23:27:27 -070076 "marvell,88q2220", &len);
xjb04a4022021-11-25 15:01:52 +080077 if (!paddr)
78 return 0;
79
80 speed = be32_to_cpup(paddr);
81 master = be32_to_cpup(paddr + 1);
xjb04a4022021-11-25 15:01:52 +080082 val = phy_read(phydev, Q2110_T1_PMA_PMD_CTRL);
83 if (val < 0)
84 return val;
85 val &= ~(Q2110_T1_MASTER_SLAVE_CFG | Q2110_T1_LINK_TYPE);
86 if (speed == SPEED_1000)
87 val |= Q2110_T1_LINK_TYPE;
88 if (master)
89 val |= Q2110_T1_MASTER_SLAVE_CFG;
90 val = phy_write(phydev, Q2110_T1_PMA_PMD_CTRL, val);
91 if (val < 0)
92 return val;
lxf359d1312023-07-28 04:04:02 -070093/*
ll3e22ca62022-06-22 10:50:31 +080094 phy_write(phydev, (MII_ADDR_C45 | 0x030900), 0x8000);
95 phy_write(phydev, (MII_ADDR_C45 | 0x03FFE4), 0x000C);
lxf359d1312023-07-28 04:04:02 -070096*/
c.chenbaa06e92022-04-17 23:27:27 -070097 printk("q2110 dts init ok!!\n");
xjb04a4022021-11-25 15:01:52 +080098
99 return 0;
100}
101
102static int q2110_timing_init(struct phy_device *phydev)
103{
104 int val;
105
106 if (phy_interface_is_rgmii(phydev)) {
107 val = phy_read(phydev, Q2110_COM_PORT_CTRL);
108 if (val < 0)
109 return val;
110
111 val &= ~(Q2110_RGMII_TX_TIMING_CTRL |
112 Q2110_RGMII_RX_TIMING_CTRL);
113
114 if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID)
115 val |= (Q2110_RGMII_TX_TIMING_CTRL |
116 Q2110_RGMII_RX_TIMING_CTRL);
117 else if (phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID)
118 val |= Q2110_RGMII_RX_TIMING_CTRL;
119 else if (phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID)
120 val |= Q2110_RGMII_TX_TIMING_CTRL;
121
122 val = phy_write(phydev, Q2110_COM_PORT_CTRL, val);
123 if (val < 0)
124 return val;
125 }
126
c.chenbaa06e92022-04-17 23:27:27 -0700127
xjb04a4022021-11-25 15:01:52 +0800128 val = phy_read(phydev, Q2110_RST_CTRL);
129 if (val < 0)
130 return val;
131 val |= Q2110_RGMII_SW_RESET;
132 val = phy_write(phydev, Q2110_RST_CTRL, val);
133 if (val < 0)
134 return val;
135
xjb04a4022021-11-25 15:01:52 +0800136 val = phy_read(phydev, Q2110_RST_CTRL);
137 if (val < 0)
138 return val;
139 val &= ~Q2110_RGMII_SW_RESET;
140 val = phy_write(phydev, Q2110_RST_CTRL, val);
141 if (val < 0)
142 return val;
143
144 return 0;
145}
146
lxf359d1312023-07-28 04:04:02 -0700147static int q2220_b0_config_init(struct phy_device *phydev)
xjb04a4022021-11-25 15:01:52 +0800148{
ll3e22ca62022-06-22 10:50:31 +0800149 int i=0,mrvlId;
xjb04a4022021-11-25 15:01:52 +0800150 phydev->supported =
151 SUPPORTED_1000baseT_Full | SUPPORTED_100baseT_Full;
152 phydev->advertising =
153 SUPPORTED_1000baseT_Full | SUPPORTED_100baseT_Full;
154 phydev->state = PHY_NOLINK;
155 phydev->autoneg = AUTONEG_DISABLE;
lxf359d1312023-07-28 04:04:02 -0700156
157 printk("PHY_DEVICE is B0");
c.chenfaec22c2022-07-27 19:38:31 -0700158 phy_write(phydev, MII_ADDR_C45 | 0x038033, 0x6801);
xf.li57bccfc2023-07-18 23:51:06 -0700159 phy_write(phydev, MII_ADDR_C45 | 0x070200, 0x0000U);
ll3e22ca62022-06-22 10:50:31 +0800160 phy_write(phydev, MII_ADDR_C45 | 0x010000, 0x840);
161 phy_write(phydev, MII_ADDR_C45 | 0x03FE1B, 0x48);
162 phy_write(phydev, MII_ADDR_C45 | 0x01FFE4, 0x6B6);
163 phy_write(phydev, MII_ADDR_C45 | 0x010000, 0x0);
164 phy_write(phydev, MII_ADDR_C45 | 0x030000, 0x0);
165 while (i < 5) {
166 mrvlId= phy_read(phydev, MII_ADDR_C45 | 0x03FFE4);
167 if (mrvlId == 0x06BA) {
168 break;
169 }
170 i++;
171 msleep(1);
172 }
173 phy_write(phydev, MII_ADDR_C45 | 0x078032, 0x2020);
174 phy_write(phydev, MII_ADDR_C45 | 0x078031, 0xA28);
175 phy_write(phydev, MII_ADDR_C45 | 0x078031, 0xC28);
xf.li57bccfc2023-07-18 23:51:06 -0700176 phy_write(phydev, MII_ADDR_C45 | 0x03FFDB, 0xFC10);
177 phy_write(phydev, MII_ADDR_C45 | 0x03FE1B, 0x58);
lxf359d1312023-07-28 04:04:02 -0700178//cheng.c modify for ethernet can not link up with golden device
179 phy_write(phydev, MII_ADDR_C45 | 0x03803A, 0xDA44);
180 phy_write(phydev, MII_ADDR_C45 | 0x038039, 0x2C0B);
181
182 phy_write(phydev, MII_ADDR_C45 | 0x038027, 0x1);//TC10 sleep/wakeup capability support
183 q2110_timing_init(phydev);
184
185 q2110_dts_init(phydev);
186
187 //softResetGe
188 phy_write(phydev, (MII_ADDR_C45 | 0x03FE1B), 0x48);
189 phy_write(phydev, (MII_ADDR_C45 | 0x030900), 0x8000);
190 phy_write(phydev, (MII_ADDR_C45 | 0x03FFE4), 0x000C);
191 phy_write(phydev, (MII_ADDR_C45 | 0x03FE1B), 0x58);
192
193 #if 0
194 //FE/100BT1
195 phy_write(phydev, (MII_ADDR_C45 | 0x030900), 0x8000);
196 phy_write(phydev, (MII_ADDR_C45 | 0x03FFE4), 0x000C);
197 #endif
198 printk("phy init ok\n");
199 return 0;
200}
201
202static int q2220_b1_config_init(struct phy_device *phydev)
203{
204
205 phydev->supported =
206 SUPPORTED_1000baseT_Full | SUPPORTED_100baseT_Full;
207 phydev->advertising =
208 SUPPORTED_1000baseT_Full | SUPPORTED_100baseT_Full;
209 phydev->state = PHY_NOLINK;
210 phydev->autoneg = AUTONEG_DISABLE;
211
212
213 printk("PHY_DEVICE is B1");
214 /* set power management state breakpoint (internal state) */
215 phy_write(phydev, MII_ADDR_C45 | 0x03FFE4, 0x0007);
216 /* disable ANEG */
217 phy_write(phydev, MII_ADDR_C45 | 0x070200, 0x0000U);
218 /* prepare to write init code */
219 /* enable TXDAC setting overwrite bit */
220 phy_write(phydev, MII_ADDR_C45 | 0x03ffe3, 0x7000);
221 /* set IEEE power down */
222 phy_write(phydev, MII_ADDR_C45 | 0x010000, 0x0840);
223 /* wait 3 ms to get to ON_TBGB State and send out WUP if needed */
224 mdelay(3);
225 /* exit standby state(internal state) */
226 phy_write(phydev, MII_ADDR_C45 | 0x03FE1B, 0x0048);
227 /* exit IEEE power down */
228 phy_write(phydev, MII_ADDR_C45 | 0x010000, 0x0000);
229 phy_write(phydev, MII_ADDR_C45 | 0x030000, 0x0000);
230 /* configure TC10 loc_act_detect for rev B1 */
231 phy_write(phydev, MII_ADDR_C45 | 0x03FCAD, 0x030C);
232 phy_write(phydev, MII_ADDR_C45 | 0x038032, 0x6001);
233 phy_write(phydev, MII_ADDR_C45 | 0x03FDFF, 0x05A5);
234 phy_write(phydev, MII_ADDR_C45 | 0x03FDEC, 0xDBAF);
235 phy_write(phydev, MII_ADDR_C45 | 0x03FCAB, 0x1054);
236 phy_write(phydev, MII_ADDR_C45 | 0x03FCAC, 0x1483);
237 /* set DISABLE_WAIT_COMM to 0 for WUR */
238 phy_write(phydev, MII_ADDR_C45 | 0x038033, 0xC801);
239 /* send_s detection threshold, slave and master */
240 phy_write(phydev, MII_ADDR_C45 | 0x78032, 0x2020);
241 phy_write(phydev, MII_ADDR_C45 | 0x78031, 0xA28);
242 phy_write(phydev, MII_ADDR_C45 | 0x78031, 0xC28);
243 /* disable DCL calibratin during tear down */
244 phy_write(phydev, MII_ADDR_C45 | 0x03FFDB, 0xFC10);
245 /* disable RESET of DCL*/
246 phy_write(phydev, MII_ADDR_C45 | 0x03FE1B, 0x58);
247 /* update Initial FFE Coefficients */
248 phy_write(phydev, MII_ADDR_C45 | 0x03FBBA, 0x0CB2);
249 phy_write(phydev, MII_ADDR_C45 | 0x03FBBB, 0x0C4A);
250 /* Toggle Squelch override */
251 phy_write(phydev, MII_ADDR_C45 | 0x048178, 0x7540);
252 phy_write(phydev, MII_ADDR_C45 | 0x048178, 0x5540);
253 /* aneg set pga gain and amp */
254 phy_write(phydev, MII_ADDR_C45 | 0x03FE5F, 0xE8);
255 phy_write(phydev, MII_ADDR_C45 | 0x03FE05, 0x755C);
xf.li57bccfc2023-07-18 23:51:06 -0700256
c.chenfaec22c2022-07-27 19:38:31 -0700257 phy_write(phydev, MII_ADDR_C45 | 0x03803A, 0xDA44);
258 phy_write(phydev, MII_ADDR_C45 | 0x038039, 0x2C0B);
c.chendf3ef622022-07-13 00:57:58 -0700259
lxf250227e2023-08-16 18:05:03 -0700260 phy_write(phydev, MII_ADDR_C45 | 0x038027, 0x0);//TC10 sleep/wakeup capability disable
xjb04a4022021-11-25 15:01:52 +0800261 q2110_timing_init(phydev);
262
ll3e22ca62022-06-22 10:50:31 +0800263 q2110_dts_init(phydev);
lxf359d1312023-07-28 04:04:02 -0700264
265 //softResetGe
266 phy_write(phydev, (MII_ADDR_C45 | 0x03FE1B), 0x48);
267 phy_write(phydev, (MII_ADDR_C45 | 0x030900), 0x8000);
268 phy_write(phydev, (MII_ADDR_C45 | 0x03FFE4), 0x000C);
269 phy_write(phydev, (MII_ADDR_C45 | 0x03FE1B), 0x58);
270
271 #if 0
272 //FE/100BT1
273 phy_write(phydev, (MII_ADDR_C45 | 0x030900), 0x8000);
274 phy_write(phydev, (MII_ADDR_C45 | 0x03FFE4), 0x000C);
275 #endif
xf.li57bccfc2023-07-18 23:51:06 -0700276 printk("phy init ok\n");
xjb04a4022021-11-25 15:01:52 +0800277 return 0;
278}
279
280static int q2110_loopback(struct phy_device *phydev, bool enable)
281{
282 int val;
283
284 val = phy_read(phydev, Q2110_PCS_CTRL);
285 if (val < 0)
286 return val;
287
288 val &= ~Q2110_LOOPBACK;
289 if (enable)
290 val |= Q2110_LOOPBACK;
291
292 val = phy_write(phydev, Q2110_PCS_CTRL, val);
293 if (val < 0)
294 return val;
295
296 return 0;
297}
298
c.chenbaa06e92022-04-17 23:27:27 -0700299
xjb04a4022021-11-25 15:01:52 +0800300static int q2110_read_status(struct phy_device *phydev)
301{
302 int val;
xf.li2b504092023-07-26 00:14:02 -0700303 unsigned int regVal1, regVal2, regVal3;
xjb04a4022021-11-25 15:01:52 +0800304
305 phydev->duplex = 1;
306 phydev->pause = 0;
307
xf.li2b504092023-07-26 00:14:02 -0700308 regVal1 = phy_read(phydev, MII_ADDR_C45 | 0x030901);
309 regVal1 = phy_read(phydev, MII_ADDR_C45 | 0x030901);
310 regVal2 = phy_read(phydev, MII_ADDR_C45 | 0x078001);
311 regVal3 = phy_read(phydev, MII_ADDR_C45 | 0x03FD9D);
312
313 phydev->link = ((0x0004U == (regVal1 & 0x0004U))
314 && (0x3000U == (regVal2 & 0x3000U))
315 && (0x0010U == (regVal3 & 0x0010U))) ? 1 : 0;
316 if(phydev->link == 0)
317 {
318 printk("phy_link_status down: regVal1: %x, regVal2: %x, regVal3: %x.\n",regVal1, regVal2, regVal3);
319 }
320/* val = phy_read(phydev, Q2110_T1_AN_STATUS);
xjb04a4022021-11-25 15:01:52 +0800321 if (val < 0)
322 return val;
323
xjb04a4022021-11-25 15:01:52 +0800324 if (val & Q2110_T1_LINK_STATUS)
325 phydev->link = 1;
326 else
327 phydev->link = 0;
xf.li2b504092023-07-26 00:14:02 -0700328*/
xjb04a4022021-11-25 15:01:52 +0800329 val = phy_read(phydev, Q2110_T1_PMA_PMD_CTRL);
330 if (val < 0)
331 return val;
332
333 if (val & Q2110_T1_LINK_TYPE)
334 phydev->speed = SPEED_1000;
335 else
336 phydev->speed = SPEED_100;
337
338 return 0;
339}
340
c.chenae2fc652022-07-11 03:54:53 -0700341int q2220_suspend(struct phy_device *phydev)
342{
xf.liec75fdd2022-11-09 18:24:10 -0800343 //xf.li 2022/11/9 modify for API-647
xf.li2230aac2022-09-09 00:23:23 -0700344 printk("phy sleep start\n");
xf.li9d095322023-02-07 18:04:49 -0800345 gpio_direction_output(NAD_WAKEUP_PHY1, 0);
346 mdelay(1);//ensure do not wake up
347 //phy_write(phydev, MII_ADDR_C45 | 0x038022, 0x1);
348 phy_write(phydev, Q2220_LPSD_CTRL_1, Q2220_LPSD_DISABLE_REMOTE_WAKE_UP);
349 mdelay(10);//for enter T1 port sleep, need link parter respond
350 printk("reg 038021 = %x\n", phy_read(phydev, Q2220_LPSD_CTRL_1));
351 phy_write(phydev, Q2220_LPSD_STATUS, Q2220_LPSD_POWER_DOWN);// enter LPSD sleep mode
352 printk("reg 038020 = %x\n", phy_read(phydev, Q2220_LPSD_STATUS));
353 mdelay(50);
354 printk("reg 038020 = %x\n", phy_read(phydev, Q2220_LPSD_STATUS));
355 gpio_direction_output(NAD_RESET_PHY1, 0);
xf.li742b5c02023-04-01 02:05:52 -0700356 mdelay(1);
357 gpio_direction_output(PHY_POWER_SUPPLY, 0);
xf.liec75fdd2022-11-09 18:24:10 -0800358 if_suspend = 1;
xf.li2230aac2022-09-09 00:23:23 -0700359 return 0;
xf.liec75fdd2022-11-09 18:24:10 -0800360 //xf.li 2022/11/9 modify for API-647
c.chenae2fc652022-07-11 03:54:53 -0700361}
lxf359d1312023-07-28 04:04:02 -0700362int q2220_b0_resume(struct phy_device *phydev)
c.chenae2fc652022-07-11 03:54:53 -0700363{
xf.liec75fdd2022-11-09 18:24:10 -0800364 //xf.li 2022/11/9 modify for API-647
365 if(if_suspend == 1)
366 {
367 printk("phy awake start\n");
xf.li742b5c02023-04-01 02:05:52 -0700368 gpio_direction_output(PHY_POWER_SUPPLY, 1);
369 mdelay(1);
xf.li9d095322023-02-07 18:04:49 -0800370 gpio_direction_output(NAD_WAKEUP_PHY1, 1);
xf.li0fdb2c82023-07-19 04:51:07 -0700371 mdelay(10);
xf.li9d095322023-02-07 18:04:49 -0800372 gpio_direction_output(NAD_WAKEUP_PHY1, 0);
xf.li0fdb2c82023-07-19 04:51:07 -0700373 mdelay(5);
374 gpio_direction_output(NAD_RESET_PHY1, 1);
lxf9df30f92023-08-02 23:22:41 -0700375 mdelay(10);
xf.li0fdb2c82023-07-19 04:51:07 -0700376 gpio_direction_output(NAD_RESET_PHY1, 0);
377 mdelay(30);
xf.li9d095322023-02-07 18:04:49 -0800378 gpio_direction_output(NAD_RESET_PHY1, 1);
379 mdelay(10);//at lest 4ms for reset phy
lxf359d1312023-07-28 04:04:02 -0700380 q2220_b0_config_init(phydev);
381 if_suspend = 0;
382 }
383 else
384 {
385 printk("q2220_resume: no suspend! In boot state.");
386 }
387 return 0;
388 //xf.li 2022/11/9 modify for API-647
389}
390
391int q2220_b1_resume(struct phy_device *phydev)
392{
393 //xf.li 2022/11/9 modify for API-647
394 if(if_suspend == 1)
395 {
396 printk("phy awake start\n");
lxf359d1312023-07-28 04:04:02 -0700397 gpio_direction_output(PHY_POWER_SUPPLY, 1);
398 mdelay(1);
399 gpio_direction_output(NAD_WAKEUP_PHY1, 1);
400 mdelay(10);
401 gpio_direction_output(NAD_WAKEUP_PHY1, 0);
402 mdelay(5);
403 gpio_direction_output(NAD_RESET_PHY1, 1);
lxf9df30f92023-08-02 23:22:41 -0700404 mdelay(10);
lxf359d1312023-07-28 04:04:02 -0700405 gpio_direction_output(NAD_RESET_PHY1, 0);
406 mdelay(30);
407 gpio_direction_output(NAD_RESET_PHY1, 1);
lxf359d1312023-07-28 04:04:02 -0700408 mdelay(10);//at lest 4ms for reset phy
409 q2220_b1_config_init(phydev);
xf.li0fdb2c82023-07-19 04:51:07 -0700410 if_suspend = 0;
xf.liec75fdd2022-11-09 18:24:10 -0800411 }
412 else
413 {
414 printk("q2220_resume: no suspend! In boot state.");
415 }
xf.li2230aac2022-09-09 00:23:23 -0700416 return 0;
xf.liec75fdd2022-11-09 18:24:10 -0800417 //xf.li 2022/11/9 modify for API-647
c.chenae2fc652022-07-11 03:54:53 -0700418}
419
420
lxf359d1312023-07-28 04:04:02 -0700421static int q2220_b0_match_phy_device(struct phy_device *phydev)
xjb04a4022021-11-25 15:01:52 +0800422{
lxf359d1312023-07-28 04:04:02 -0700423 return ((phydev->c45_ids.device_ids[1] & 0xffffffff) == PHY_ID_88Q2220_B0);
424}
425
426static int q2220_b1_match_phy_device(struct phy_device *phydev)
427{
428 return ((phydev->c45_ids.device_ids[1] & 0xffffffff) == PHY_ID_88Q2220_B1);
xjb04a4022021-11-25 15:01:52 +0800429}
430
431static struct phy_driver marvell_88q_driver[] = {
432 {
lxf359d1312023-07-28 04:04:02 -0700433 .phy_id = PHY_ID_88Q2220_B0,
xjb04a4022021-11-25 15:01:52 +0800434 .phy_id_mask = 0xfffffff0,
lxf359d1312023-07-28 04:04:02 -0700435 .name = "Marvell 88Q2220 B0",
436 .config_init = q2220_b0_config_init,
437 .match_phy_device = q2220_b0_match_phy_device,
xjb04a4022021-11-25 15:01:52 +0800438 .set_loopback = &q2110_loopback,
439 .read_status = q2110_read_status,
c.chenae2fc652022-07-11 03:54:53 -0700440 .suspend = q2220_suspend,
lxf359d1312023-07-28 04:04:02 -0700441 .resume = q2220_b0_resume,
442 }, {
443 .phy_id = PHY_ID_88Q2220_B1,
444 .phy_id_mask = 0xfffffff0,
445 .name = "Marvell 88Q2220 B1",
446 .config_init = q2220_b1_config_init,
447 .match_phy_device = q2220_b1_match_phy_device,
448 .set_loopback = &q2110_loopback,
449 .read_status = q2110_read_status,
450 .suspend = q2220_suspend,
451 .resume = q2220_b1_resume,
xjb04a4022021-11-25 15:01:52 +0800452 }
453};
454
455module_phy_driver(marvell_88q_driver);