xref: /linux/drivers/net/phy/as21xxx.c (revision ab93e0dd72c37d378dd936f031ffb83ff2bd87ce)
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Aeonsemi AS21XXxX PHY Driver
4  *
5  * Author: Christian Marangi <ansuelsmth@gmail.com>
6  */
7 
8 #include <linux/bitfield.h>
9 #include <linux/firmware.h>
10 #include <linux/module.h>
11 #include <linux/of.h>
12 #include <linux/phy.h>
13 
14 #define VEND1_GLB_REG_CPU_RESET_ADDR_LO_BASEADDR 0x3
15 #define VEND1_GLB_REG_CPU_RESET_ADDR_HI_BASEADDR 0x4
16 
17 #define VEND1_GLB_REG_CPU_CTRL		0xe
18 #define   VEND1_GLB_CPU_CTRL_MASK	GENMASK(4, 0)
19 #define   VEND1_GLB_CPU_CTRL_LED_POLARITY_MASK GENMASK(12, 8)
20 #define   VEND1_GLB_CPU_CTRL_LED_POLARITY(_n) FIELD_PREP(VEND1_GLB_CPU_CTRL_LED_POLARITY_MASK, \
21 							 BIT(_n))
22 
23 #define VEND1_FW_START_ADDR		0x100
24 
25 #define VEND1_GLB_REG_MDIO_INDIRECT_ADDRCMD 0x101
26 #define VEND1_GLB_REG_MDIO_INDIRECT_LOAD 0x102
27 
28 #define VEND1_GLB_REG_MDIO_INDIRECT_STATUS 0x103
29 
30 #define VEND1_PTP_CLK			0x142
31 #define   VEND1_PTP_CLK_EN		BIT(6)
32 
33 /* 5 LED at step of 0x20
34  * FE: Fast-Ethernet (10/100)
35  * GE: Gigabit-Ethernet (1000)
36  * NG: New-Generation (2500/5000/10000)
37  */
38 #define VEND1_LED_REG(_n)		(0x1800 + ((_n) * 0x10))
39 #define   VEND1_LED_REG_A_EVENT		GENMASK(15, 11)
40 #define VEND1_LED_CONF			0x1881
41 #define   VEND1_LED_CONFG_BLINK		GENMASK(7, 0)
42 
43 #define VEND1_SPEED_STATUS		0x4002
44 #define   VEND1_SPEED_MASK		GENMASK(7, 0)
45 #define   VEND1_SPEED_10000		FIELD_PREP_CONST(VEND1_SPEED_MASK, 0x3)
46 #define   VEND1_SPEED_5000		FIELD_PREP_CONST(VEND1_SPEED_MASK, 0x5)
47 #define   VEND1_SPEED_2500		FIELD_PREP_CONST(VEND1_SPEED_MASK, 0x9)
48 #define   VEND1_SPEED_1000		FIELD_PREP_CONST(VEND1_SPEED_MASK, 0x10)
49 #define   VEND1_SPEED_100		FIELD_PREP_CONST(VEND1_SPEED_MASK, 0x20)
50 #define   VEND1_SPEED_10		FIELD_PREP_CONST(VEND1_SPEED_MASK, 0x0)
51 
52 #define VEND1_IPC_CMD			0x5801
53 #define   AEON_IPC_CMD_PARITY		BIT(15)
54 #define   AEON_IPC_CMD_SIZE		GENMASK(10, 6)
55 #define   AEON_IPC_CMD_OPCODE		GENMASK(5, 0)
56 
57 #define IPC_CMD_NOOP			0x0  /* Do nothing */
58 #define IPC_CMD_INFO			0x1  /* Get Firmware Version */
59 #define IPC_CMD_SYS_CPU			0x2  /* SYS_CPU */
60 #define IPC_CMD_BULK_DATA		0xa  /* Pass bulk data in ipc registers. */
61 #define IPC_CMD_BULK_WRITE		0xc  /* Write bulk data to memory */
62 #define IPC_CMD_CFG_PARAM		0x1a /* Write config parameters to memory */
63 #define IPC_CMD_NG_TESTMODE		0x1b /* Set NG test mode and tone */
64 #define IPC_CMD_TEMP_MON		0x15 /* Temperature monitoring function */
65 #define IPC_CMD_SET_LED			0x23 /* Set led */
66 
67 #define VEND1_IPC_STS			0x5802
68 #define   AEON_IPC_STS_PARITY		BIT(15)
69 #define   AEON_IPC_STS_SIZE		GENMASK(14, 10)
70 #define   AEON_IPC_STS_OPCODE		GENMASK(9, 4)
71 #define   AEON_IPC_STS_STATUS		GENMASK(3, 0)
72 #define   AEON_IPC_STS_STATUS_RCVD	FIELD_PREP_CONST(AEON_IPC_STS_STATUS, 0x1)
73 #define   AEON_IPC_STS_STATUS_PROCESS	FIELD_PREP_CONST(AEON_IPC_STS_STATUS, 0x2)
74 #define   AEON_IPC_STS_STATUS_SUCCESS	FIELD_PREP_CONST(AEON_IPC_STS_STATUS, 0x4)
75 #define   AEON_IPC_STS_STATUS_ERROR	FIELD_PREP_CONST(AEON_IPC_STS_STATUS, 0x8)
76 #define   AEON_IPC_STS_STATUS_BUSY	FIELD_PREP_CONST(AEON_IPC_STS_STATUS, 0xe)
77 #define   AEON_IPC_STS_STATUS_READY	FIELD_PREP_CONST(AEON_IPC_STS_STATUS, 0xf)
78 
79 #define VEND1_IPC_DATA0			0x5808
80 #define VEND1_IPC_DATA1			0x5809
81 #define VEND1_IPC_DATA2			0x580a
82 #define VEND1_IPC_DATA3			0x580b
83 #define VEND1_IPC_DATA4			0x580c
84 #define VEND1_IPC_DATA5			0x580d
85 #define VEND1_IPC_DATA6			0x580e
86 #define VEND1_IPC_DATA7			0x580f
87 #define VEND1_IPC_DATA(_n)		(VEND1_IPC_DATA0 + (_n))
88 
89 /* Sub command of CMD_INFO */
90 #define IPC_INFO_VERSION		0x1
91 
92 /* Sub command of CMD_SYS_CPU */
93 #define IPC_SYS_CPU_REBOOT		0x3
94 #define IPC_SYS_CPU_IMAGE_OFST		0x4
95 #define IPC_SYS_CPU_IMAGE_CHECK		0x5
96 #define IPC_SYS_CPU_PHY_ENABLE		0x6
97 
98 /* Sub command of CMD_CFG_PARAM */
99 #define IPC_CFG_PARAM_DIRECT		0x4
100 
101 /* CFG DIRECT sub command */
102 #define IPC_CFG_PARAM_DIRECT_NG_PHYCTRL	0x1
103 #define IPC_CFG_PARAM_DIRECT_CU_AN	0x2
104 #define IPC_CFG_PARAM_DIRECT_SDS_PCS	0x3
105 #define IPC_CFG_PARAM_DIRECT_AUTO_EEE	0x4
106 #define IPC_CFG_PARAM_DIRECT_SDS_PMA	0x5
107 #define IPC_CFG_PARAM_DIRECT_DPC_RA	0x6
108 #define IPC_CFG_PARAM_DIRECT_DPC_PKT_CHK 0x7
109 #define IPC_CFG_PARAM_DIRECT_DPC_SDS_WAIT_ETH 0x8
110 #define IPC_CFG_PARAM_DIRECT_WDT	0x9
111 #define IPC_CFG_PARAM_DIRECT_SDS_RESTART_AN 0x10
112 #define IPC_CFG_PARAM_DIRECT_TEMP_MON	0x11
113 #define IPC_CFG_PARAM_DIRECT_WOL	0x12
114 
115 /* Sub command of CMD_TEMP_MON */
116 #define IPC_CMD_TEMP_MON_GET		0x4
117 
118 #define AS21XXX_MDIO_AN_C22		0xffe0
119 
120 #define PHY_ID_AS21XXX			0x75009410
121 /* AS21xxx ID Legend
122  * AS21x1xxB1
123  *     ^ ^^
124  *     | |J: Supports SyncE/PTP
125  *     | |P: No SyncE/PTP support
126  *     | 1: Supports 2nd Serdes
127  *     | 2: Not 2nd Serdes support
128  *     0: 10G, 5G, 2.5G
129  *     5: 5G, 2.5G
130  *     2: 2.5G
131  */
132 #define PHY_ID_AS21011JB1		0x75009402
133 #define PHY_ID_AS21011PB1		0x75009412
134 #define PHY_ID_AS21010JB1		0x75009422
135 #define PHY_ID_AS21010PB1		0x75009432
136 #define PHY_ID_AS21511JB1		0x75009442
137 #define PHY_ID_AS21511PB1		0x75009452
138 #define PHY_ID_AS21510JB1		0x75009462
139 #define PHY_ID_AS21510PB1		0x75009472
140 #define PHY_ID_AS21210JB1		0x75009482
141 #define PHY_ID_AS21210PB1		0x75009492
142 #define PHY_VENDOR_AEONSEMI		0x75009400
143 
144 #define AEON_MAX_LEDS			5
145 #define AEON_IPC_DELAY			10000
146 #define AEON_IPC_TIMEOUT		(AEON_IPC_DELAY * 100)
147 #define AEON_IPC_DATA_NUM_REGISTERS	8
148 #define AEON_IPC_DATA_MAX		(AEON_IPC_DATA_NUM_REGISTERS * sizeof(u16))
149 
150 #define AEON_BOOT_ADDR			0x1000
151 #define AEON_CPU_BOOT_ADDR		0x2000
152 #define AEON_CPU_CTRL_FW_LOAD		(BIT(4) | BIT(2) | BIT(1) | BIT(0))
153 #define AEON_CPU_CTRL_FW_START		BIT(0)
154 
155 enum as21xxx_led_event {
156 	VEND1_LED_REG_A_EVENT_ON_10 = 0x0,
157 	VEND1_LED_REG_A_EVENT_ON_100,
158 	VEND1_LED_REG_A_EVENT_ON_1000,
159 	VEND1_LED_REG_A_EVENT_ON_2500,
160 	VEND1_LED_REG_A_EVENT_ON_5000,
161 	VEND1_LED_REG_A_EVENT_ON_10000,
162 	VEND1_LED_REG_A_EVENT_ON_FE_GE,
163 	VEND1_LED_REG_A_EVENT_ON_NG,
164 	VEND1_LED_REG_A_EVENT_ON_FULL_DUPLEX,
165 	VEND1_LED_REG_A_EVENT_ON_COLLISION,
166 	VEND1_LED_REG_A_EVENT_BLINK_TX,
167 	VEND1_LED_REG_A_EVENT_BLINK_RX,
168 	VEND1_LED_REG_A_EVENT_BLINK_ACT,
169 	VEND1_LED_REG_A_EVENT_ON_LINK,
170 	VEND1_LED_REG_A_EVENT_ON_LINK_BLINK_ACT,
171 	VEND1_LED_REG_A_EVENT_ON_LINK_BLINK_RX,
172 	VEND1_LED_REG_A_EVENT_ON_FE_GE_BLINK_ACT,
173 	VEND1_LED_REG_A_EVENT_ON_NG_BLINK_ACT,
174 	VEND1_LED_REG_A_EVENT_ON_NG_BLINK_FE_GE,
175 	VEND1_LED_REG_A_EVENT_ON_FD_BLINK_COLLISION,
176 	VEND1_LED_REG_A_EVENT_ON,
177 	VEND1_LED_REG_A_EVENT_OFF,
178 };
179 
180 struct as21xxx_led_pattern_info {
181 	unsigned int pattern;
182 	u16 val;
183 };
184 
185 struct as21xxx_priv {
186 	bool parity_status;
187 	/* Protect concurrent IPC access */
188 	struct mutex ipc_lock;
189 };
190 
191 static struct as21xxx_led_pattern_info as21xxx_led_supported_pattern[] = {
192 	{
193 		.pattern = BIT(TRIGGER_NETDEV_LINK_10),
194 		.val = VEND1_LED_REG_A_EVENT_ON_10
195 	},
196 	{
197 		.pattern = BIT(TRIGGER_NETDEV_LINK_100),
198 		.val = VEND1_LED_REG_A_EVENT_ON_100
199 	},
200 	{
201 		.pattern = BIT(TRIGGER_NETDEV_LINK_1000),
202 		.val = VEND1_LED_REG_A_EVENT_ON_1000
203 	},
204 	{
205 		.pattern = BIT(TRIGGER_NETDEV_LINK_2500),
206 		.val = VEND1_LED_REG_A_EVENT_ON_2500
207 	},
208 	{
209 		.pattern = BIT(TRIGGER_NETDEV_LINK_5000),
210 		.val = VEND1_LED_REG_A_EVENT_ON_5000
211 	},
212 	{
213 		.pattern = BIT(TRIGGER_NETDEV_LINK_10000),
214 		.val = VEND1_LED_REG_A_EVENT_ON_10000
215 	},
216 	{
217 		.pattern = BIT(TRIGGER_NETDEV_LINK),
218 		.val = VEND1_LED_REG_A_EVENT_ON_LINK
219 	},
220 	{
221 		.pattern = BIT(TRIGGER_NETDEV_LINK_10) |
222 			   BIT(TRIGGER_NETDEV_LINK_100) |
223 			   BIT(TRIGGER_NETDEV_LINK_1000),
224 		.val = VEND1_LED_REG_A_EVENT_ON_FE_GE
225 	},
226 	{
227 		.pattern = BIT(TRIGGER_NETDEV_LINK_2500) |
228 			   BIT(TRIGGER_NETDEV_LINK_5000) |
229 			   BIT(TRIGGER_NETDEV_LINK_10000),
230 		.val = VEND1_LED_REG_A_EVENT_ON_NG
231 	},
232 	{
233 		.pattern = BIT(TRIGGER_NETDEV_FULL_DUPLEX),
234 		.val = VEND1_LED_REG_A_EVENT_ON_FULL_DUPLEX
235 	},
236 	{
237 		.pattern = BIT(TRIGGER_NETDEV_TX),
238 		.val = VEND1_LED_REG_A_EVENT_BLINK_TX
239 	},
240 	{
241 		.pattern = BIT(TRIGGER_NETDEV_RX),
242 		.val = VEND1_LED_REG_A_EVENT_BLINK_RX
243 	},
244 	{
245 		.pattern = BIT(TRIGGER_NETDEV_TX) |
246 			   BIT(TRIGGER_NETDEV_RX),
247 		.val = VEND1_LED_REG_A_EVENT_BLINK_ACT
248 	},
249 	{
250 		.pattern = BIT(TRIGGER_NETDEV_LINK_10) |
251 			   BIT(TRIGGER_NETDEV_LINK_100) |
252 			   BIT(TRIGGER_NETDEV_LINK_1000) |
253 			   BIT(TRIGGER_NETDEV_LINK_2500) |
254 			   BIT(TRIGGER_NETDEV_LINK_5000) |
255 			   BIT(TRIGGER_NETDEV_LINK_10000),
256 		.val = VEND1_LED_REG_A_EVENT_ON_LINK
257 	},
258 	{
259 		.pattern = BIT(TRIGGER_NETDEV_LINK_10) |
260 			   BIT(TRIGGER_NETDEV_LINK_100) |
261 			   BIT(TRIGGER_NETDEV_LINK_1000) |
262 			   BIT(TRIGGER_NETDEV_LINK_2500) |
263 			   BIT(TRIGGER_NETDEV_LINK_5000) |
264 			   BIT(TRIGGER_NETDEV_LINK_10000) |
265 			   BIT(TRIGGER_NETDEV_TX) |
266 			   BIT(TRIGGER_NETDEV_RX),
267 		.val = VEND1_LED_REG_A_EVENT_ON_LINK_BLINK_ACT
268 	},
269 	{
270 		.pattern = BIT(TRIGGER_NETDEV_LINK_10) |
271 			   BIT(TRIGGER_NETDEV_LINK_100) |
272 			   BIT(TRIGGER_NETDEV_LINK_1000) |
273 			   BIT(TRIGGER_NETDEV_LINK_2500) |
274 			   BIT(TRIGGER_NETDEV_LINK_5000) |
275 			   BIT(TRIGGER_NETDEV_LINK_10000) |
276 			   BIT(TRIGGER_NETDEV_RX),
277 		.val = VEND1_LED_REG_A_EVENT_ON_LINK_BLINK_RX
278 	},
279 	{
280 		.pattern = BIT(TRIGGER_NETDEV_LINK_10) |
281 			   BIT(TRIGGER_NETDEV_LINK_100) |
282 			   BIT(TRIGGER_NETDEV_LINK_1000) |
283 			   BIT(TRIGGER_NETDEV_TX) |
284 			   BIT(TRIGGER_NETDEV_RX),
285 		.val = VEND1_LED_REG_A_EVENT_ON_FE_GE_BLINK_ACT
286 	},
287 	{
288 		.pattern = BIT(TRIGGER_NETDEV_LINK_2500) |
289 			   BIT(TRIGGER_NETDEV_LINK_5000) |
290 			   BIT(TRIGGER_NETDEV_LINK_10000) |
291 			   BIT(TRIGGER_NETDEV_TX) |
292 			   BIT(TRIGGER_NETDEV_RX),
293 		.val = VEND1_LED_REG_A_EVENT_ON_NG_BLINK_ACT
294 	}
295 };
296 
aeon_firmware_boot(struct phy_device * phydev,const u8 * data,size_t size)297 static int aeon_firmware_boot(struct phy_device *phydev, const u8 *data,
298 			      size_t size)
299 {
300 	int i, ret;
301 	u16 val;
302 
303 	ret = phy_modify_mmd(phydev, MDIO_MMD_VEND1, VEND1_GLB_REG_CPU_CTRL,
304 			     VEND1_GLB_CPU_CTRL_MASK, AEON_CPU_CTRL_FW_LOAD);
305 	if (ret)
306 		return ret;
307 
308 	ret = phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_FW_START_ADDR,
309 			    AEON_BOOT_ADDR);
310 	if (ret)
311 		return ret;
312 
313 	ret = phy_modify_mmd(phydev, MDIO_MMD_VEND1,
314 			     VEND1_GLB_REG_MDIO_INDIRECT_ADDRCMD,
315 			     0x3ffc, 0xc000);
316 	if (ret)
317 		return ret;
318 
319 	val = phy_read_mmd(phydev, MDIO_MMD_VEND1,
320 			   VEND1_GLB_REG_MDIO_INDIRECT_STATUS);
321 	if (val > 1) {
322 		phydev_err(phydev, "wrong origin mdio_indirect_status: %x\n", val);
323 		return -EINVAL;
324 	}
325 
326 	/* Firmware is always aligned to u16 */
327 	for (i = 0; i < size; i += 2) {
328 		val = data[i + 1] << 8 | data[i];
329 
330 		ret = phy_write_mmd(phydev, MDIO_MMD_VEND1,
331 				    VEND1_GLB_REG_MDIO_INDIRECT_LOAD, val);
332 		if (ret)
333 			return ret;
334 	}
335 
336 	ret = phy_write_mmd(phydev, MDIO_MMD_VEND1,
337 			    VEND1_GLB_REG_CPU_RESET_ADDR_LO_BASEADDR,
338 			    lower_16_bits(AEON_CPU_BOOT_ADDR));
339 	if (ret)
340 		return ret;
341 
342 	ret = phy_write_mmd(phydev, MDIO_MMD_VEND1,
343 			    VEND1_GLB_REG_CPU_RESET_ADDR_HI_BASEADDR,
344 			    upper_16_bits(AEON_CPU_BOOT_ADDR));
345 	if (ret)
346 		return ret;
347 
348 	return phy_modify_mmd(phydev, MDIO_MMD_VEND1, VEND1_GLB_REG_CPU_CTRL,
349 			      VEND1_GLB_CPU_CTRL_MASK, AEON_CPU_CTRL_FW_START);
350 }
351 
aeon_firmware_load(struct phy_device * phydev)352 static int aeon_firmware_load(struct phy_device *phydev)
353 {
354 	struct device *dev = &phydev->mdio.dev;
355 	const struct firmware *fw;
356 	const char *fw_name;
357 	int ret;
358 
359 	ret = of_property_read_string(dev->of_node, "firmware-name",
360 				      &fw_name);
361 	if (ret)
362 		return ret;
363 
364 	ret = request_firmware(&fw, fw_name, dev);
365 	if (ret) {
366 		phydev_err(phydev, "failed to find FW file %s (%d)\n",
367 			   fw_name, ret);
368 		return ret;
369 	}
370 
371 	ret = aeon_firmware_boot(phydev, fw->data, fw->size);
372 
373 	release_firmware(fw);
374 
375 	return ret;
376 }
377 
aeon_ipc_ready(u16 val,bool parity_status)378 static bool aeon_ipc_ready(u16 val, bool parity_status)
379 {
380 	u16 status;
381 
382 	if (FIELD_GET(AEON_IPC_STS_PARITY, val) != parity_status)
383 		return false;
384 
385 	status = val & AEON_IPC_STS_STATUS;
386 
387 	return status != AEON_IPC_STS_STATUS_RCVD &&
388 	       status != AEON_IPC_STS_STATUS_PROCESS &&
389 	       status != AEON_IPC_STS_STATUS_BUSY;
390 }
391 
aeon_ipc_wait_cmd(struct phy_device * phydev,bool parity_status)392 static int aeon_ipc_wait_cmd(struct phy_device *phydev, bool parity_status)
393 {
394 	u16 val;
395 
396 	/* Exit condition logic:
397 	 * - Wait for parity bit equal
398 	 * - Wait for status success, error OR ready
399 	 */
400 	return phy_read_mmd_poll_timeout(phydev, MDIO_MMD_VEND1, VEND1_IPC_STS, val,
401 					 aeon_ipc_ready(val, parity_status),
402 					 AEON_IPC_DELAY, AEON_IPC_TIMEOUT, false);
403 }
404 
aeon_ipc_send_cmd(struct phy_device * phydev,struct as21xxx_priv * priv,u16 cmd,u16 * ret_sts)405 static int aeon_ipc_send_cmd(struct phy_device *phydev,
406 			     struct as21xxx_priv *priv,
407 			     u16 cmd, u16 *ret_sts)
408 {
409 	bool curr_parity;
410 	int ret;
411 
412 	/* The IPC sync by using a single parity bit.
413 	 * Each CMD have alternately this bit set or clear
414 	 * to understand correct flow and packet order.
415 	 */
416 	curr_parity = priv->parity_status;
417 	if (priv->parity_status)
418 		cmd |= AEON_IPC_CMD_PARITY;
419 
420 	/* Always update parity for next packet */
421 	priv->parity_status = !priv->parity_status;
422 
423 	ret = phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_IPC_CMD, cmd);
424 	if (ret)
425 		return ret;
426 
427 	/* Wait for packet to be processed */
428 	usleep_range(AEON_IPC_DELAY, AEON_IPC_DELAY + 5000);
429 
430 	/* With no ret_sts, ignore waiting for packet completion
431 	 * (ipc parity bit sync)
432 	 */
433 	if (!ret_sts)
434 		return 0;
435 
436 	ret = aeon_ipc_wait_cmd(phydev, curr_parity);
437 	if (ret)
438 		return ret;
439 
440 	ret = phy_read_mmd(phydev, MDIO_MMD_VEND1, VEND1_IPC_STS);
441 	if (ret < 0)
442 		return ret;
443 
444 	*ret_sts = ret;
445 	if ((*ret_sts & AEON_IPC_STS_STATUS) != AEON_IPC_STS_STATUS_SUCCESS)
446 		return -EINVAL;
447 
448 	return 0;
449 }
450 
451 /* If data is NULL, return 0 or negative error.
452  * If data not NULL, return number of Bytes received from IPC or
453  * a negative error.
454  */
aeon_ipc_send_msg(struct phy_device * phydev,u16 opcode,u16 * data,unsigned int data_len,u16 * ret_data)455 static int aeon_ipc_send_msg(struct phy_device *phydev,
456 			     u16 opcode, u16 *data, unsigned int data_len,
457 			     u16 *ret_data)
458 {
459 	struct as21xxx_priv *priv = phydev->priv;
460 	unsigned int ret_size;
461 	u16 cmd, ret_sts;
462 	int ret;
463 	int i;
464 
465 	/* IPC have a max of 8 register to transfer data,
466 	 * make sure we never exceed this.
467 	 */
468 	if (data_len > AEON_IPC_DATA_MAX)
469 		return -EINVAL;
470 
471 	for (i = 0; i < data_len / sizeof(u16); i++)
472 		phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_IPC_DATA(i),
473 			      data[i]);
474 
475 	cmd = FIELD_PREP(AEON_IPC_CMD_SIZE, data_len) |
476 	      FIELD_PREP(AEON_IPC_CMD_OPCODE, opcode);
477 
478 	mutex_lock(&priv->ipc_lock);
479 
480 	ret = aeon_ipc_send_cmd(phydev, priv, cmd, &ret_sts);
481 	if (ret) {
482 		phydev_err(phydev, "failed to send ipc msg for %x: %d\n",
483 			   opcode, ret);
484 		goto out;
485 	}
486 
487 	if (!data)
488 		goto out;
489 
490 	if ((ret_sts & AEON_IPC_STS_STATUS) == AEON_IPC_STS_STATUS_ERROR) {
491 		ret = -EINVAL;
492 		goto out;
493 	}
494 
495 	/* Prevent IPC from stack smashing the kernel.
496 	 * We can't trust IPC to return a good value and we always
497 	 * preallocate space for 16 Bytes.
498 	 */
499 	ret_size = FIELD_GET(AEON_IPC_STS_SIZE, ret_sts);
500 	if (ret_size > AEON_IPC_DATA_MAX) {
501 		ret = -EINVAL;
502 		goto out;
503 	}
504 
505 	/* Read data from IPC data register for ret_size value from IPC */
506 	for (i = 0; i < DIV_ROUND_UP(ret_size, sizeof(u16)); i++) {
507 		ret = phy_read_mmd(phydev, MDIO_MMD_VEND1, VEND1_IPC_DATA(i));
508 		if (ret < 0)
509 			goto out;
510 
511 		ret_data[i] = ret;
512 	}
513 
514 	ret = ret_size;
515 
516 out:
517 	mutex_unlock(&priv->ipc_lock);
518 
519 	return ret;
520 }
521 
aeon_ipc_noop(struct phy_device * phydev,struct as21xxx_priv * priv,u16 * ret_sts)522 static int aeon_ipc_noop(struct phy_device *phydev,
523 			 struct as21xxx_priv *priv, u16 *ret_sts)
524 {
525 	u16 cmd;
526 
527 	cmd = FIELD_PREP(AEON_IPC_CMD_SIZE, 0) |
528 	      FIELD_PREP(AEON_IPC_CMD_OPCODE, IPC_CMD_NOOP);
529 
530 	return aeon_ipc_send_cmd(phydev, priv, cmd, ret_sts);
531 }
532 
533 /* Logic to sync parity bit with IPC.
534  * We send 2 NOP cmd with same partity and we wait for IPC
535  * to handle the packet only for the second one. This way
536  * we make sure we are sync for every next cmd.
537  */
aeon_ipc_sync_parity(struct phy_device * phydev,struct as21xxx_priv * priv)538 static int aeon_ipc_sync_parity(struct phy_device *phydev,
539 				struct as21xxx_priv *priv)
540 {
541 	u16 ret_sts;
542 	int ret;
543 
544 	mutex_lock(&priv->ipc_lock);
545 
546 	/* Send NOP with no parity */
547 	aeon_ipc_noop(phydev, priv, NULL);
548 
549 	/* Reset packet parity */
550 	priv->parity_status = false;
551 
552 	/* Send second NOP with no parity */
553 	ret = aeon_ipc_noop(phydev, priv, &ret_sts);
554 
555 	mutex_unlock(&priv->ipc_lock);
556 
557 	/* We expect to return -EINVAL */
558 	if (ret != -EINVAL)
559 		return ret;
560 
561 	if ((ret_sts & AEON_IPC_STS_STATUS) != AEON_IPC_STS_STATUS_READY) {
562 		phydev_err(phydev, "Invalid IPC status on sync parity: %x\n",
563 			   ret_sts);
564 		return -EINVAL;
565 	}
566 
567 	return 0;
568 }
569 
aeon_ipc_get_fw_version(struct phy_device * phydev)570 static int aeon_ipc_get_fw_version(struct phy_device *phydev)
571 {
572 	u16 ret_data[AEON_IPC_DATA_NUM_REGISTERS], data[1];
573 	char fw_version[AEON_IPC_DATA_MAX + 1];
574 	int ret;
575 
576 	data[0] = IPC_INFO_VERSION;
577 
578 	ret = aeon_ipc_send_msg(phydev, IPC_CMD_INFO, data,
579 				sizeof(data), ret_data);
580 	if (ret < 0)
581 		return ret;
582 
583 	/* Make sure FW version is NULL terminated */
584 	memcpy(fw_version, ret_data, ret);
585 	fw_version[ret] = '\0';
586 
587 	phydev_info(phydev, "Firmware Version: %s\n", fw_version);
588 
589 	return 0;
590 }
591 
aeon_dpc_ra_enable(struct phy_device * phydev)592 static int aeon_dpc_ra_enable(struct phy_device *phydev)
593 {
594 	u16 data[2];
595 
596 	data[0] = IPC_CFG_PARAM_DIRECT;
597 	data[1] = IPC_CFG_PARAM_DIRECT_DPC_RA;
598 
599 	return aeon_ipc_send_msg(phydev, IPC_CMD_CFG_PARAM, data,
600 				 sizeof(data), NULL);
601 }
602 
as21xxx_probe(struct phy_device * phydev)603 static int as21xxx_probe(struct phy_device *phydev)
604 {
605 	struct as21xxx_priv *priv;
606 	int ret;
607 
608 	priv = devm_kzalloc(&phydev->mdio.dev,
609 			    sizeof(*priv), GFP_KERNEL);
610 	if (!priv)
611 		return -ENOMEM;
612 	phydev->priv = priv;
613 
614 	ret = devm_mutex_init(&phydev->mdio.dev,
615 			      &priv->ipc_lock);
616 	if (ret)
617 		return ret;
618 
619 	ret = aeon_ipc_sync_parity(phydev, priv);
620 	if (ret)
621 		return ret;
622 
623 	ret = aeon_ipc_get_fw_version(phydev);
624 	if (ret)
625 		return ret;
626 
627 	/* Enable PTP clk if not already Enabled */
628 	ret = phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, VEND1_PTP_CLK,
629 			       VEND1_PTP_CLK_EN);
630 	if (ret)
631 		return ret;
632 
633 	return aeon_dpc_ra_enable(phydev);
634 }
635 
as21xxx_read_link(struct phy_device * phydev,int * bmcr)636 static int as21xxx_read_link(struct phy_device *phydev, int *bmcr)
637 {
638 	int status;
639 
640 	/* Normal C22 BMCR report inconsistent data, use
641 	 * the mapped C22 in C45 to have more consistent link info.
642 	 */
643 	*bmcr = phy_read_mmd(phydev, MDIO_MMD_AN,
644 			     AS21XXX_MDIO_AN_C22 + MII_BMCR);
645 	if (*bmcr < 0)
646 		return *bmcr;
647 
648 	/* Autoneg is being started, therefore disregard current
649 	 * link status and report link as down.
650 	 */
651 	if (*bmcr & BMCR_ANRESTART) {
652 		phydev->link = 0;
653 		return 0;
654 	}
655 
656 	status = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_STAT1);
657 	if (status < 0)
658 		return status;
659 
660 	phydev->link = !!(status & MDIO_STAT1_LSTATUS);
661 
662 	return 0;
663 }
664 
as21xxx_read_c22_lpa(struct phy_device * phydev)665 static int as21xxx_read_c22_lpa(struct phy_device *phydev)
666 {
667 	int lpagb;
668 
669 	/* MII_STAT1000 are only filled in the mapped C22
670 	 * in C45, use that to fill lpagb values and check.
671 	 */
672 	lpagb = phy_read_mmd(phydev, MDIO_MMD_AN,
673 			     AS21XXX_MDIO_AN_C22 + MII_STAT1000);
674 	if (lpagb < 0)
675 		return lpagb;
676 
677 	if (lpagb & LPA_1000MSFAIL) {
678 		int adv = phy_read_mmd(phydev, MDIO_MMD_AN,
679 				       AS21XXX_MDIO_AN_C22 + MII_CTRL1000);
680 
681 		if (adv < 0)
682 			return adv;
683 
684 		if (adv & CTL1000_ENABLE_MASTER)
685 			phydev_err(phydev, "Master/Slave resolution failed, maybe conflicting manual settings?\n");
686 		else
687 			phydev_err(phydev, "Master/Slave resolution failed\n");
688 		return -ENOLINK;
689 	}
690 
691 	mii_stat1000_mod_linkmode_lpa_t(phydev->lp_advertising,
692 					lpagb);
693 
694 	return 0;
695 }
696 
as21xxx_read_status(struct phy_device * phydev)697 static int as21xxx_read_status(struct phy_device *phydev)
698 {
699 	int bmcr, old_link = phydev->link;
700 	int ret;
701 
702 	ret = as21xxx_read_link(phydev, &bmcr);
703 	if (ret)
704 		return ret;
705 
706 	/* why bother the PHY if nothing can have changed */
707 	if (phydev->autoneg == AUTONEG_ENABLE && old_link && phydev->link)
708 		return 0;
709 
710 	phydev->speed = SPEED_UNKNOWN;
711 	phydev->duplex = DUPLEX_UNKNOWN;
712 	phydev->pause = 0;
713 	phydev->asym_pause = 0;
714 
715 	if (phydev->autoneg == AUTONEG_ENABLE) {
716 		ret = genphy_c45_read_lpa(phydev);
717 		if (ret)
718 			return ret;
719 
720 		ret = as21xxx_read_c22_lpa(phydev);
721 		if (ret)
722 			return ret;
723 
724 		phy_resolve_aneg_linkmode(phydev);
725 	} else {
726 		int speed;
727 
728 		linkmode_zero(phydev->lp_advertising);
729 
730 		speed = phy_read_mmd(phydev, MDIO_MMD_VEND1,
731 				     VEND1_SPEED_STATUS);
732 		if (speed < 0)
733 			return speed;
734 
735 		switch (speed & VEND1_SPEED_STATUS) {
736 		case VEND1_SPEED_10000:
737 			phydev->speed = SPEED_10000;
738 			phydev->duplex = DUPLEX_FULL;
739 			break;
740 		case VEND1_SPEED_5000:
741 			phydev->speed = SPEED_5000;
742 			phydev->duplex = DUPLEX_FULL;
743 			break;
744 		case VEND1_SPEED_2500:
745 			phydev->speed = SPEED_2500;
746 			phydev->duplex = DUPLEX_FULL;
747 			break;
748 		case VEND1_SPEED_1000:
749 			phydev->speed = SPEED_1000;
750 			if (bmcr & BMCR_FULLDPLX)
751 				phydev->duplex = DUPLEX_FULL;
752 			else
753 				phydev->duplex = DUPLEX_HALF;
754 			break;
755 		case VEND1_SPEED_100:
756 			phydev->speed = SPEED_100;
757 			phydev->duplex = DUPLEX_FULL;
758 			break;
759 		case VEND1_SPEED_10:
760 			phydev->speed = SPEED_10;
761 			phydev->duplex = DUPLEX_FULL;
762 			break;
763 		default:
764 			return -EINVAL;
765 		}
766 	}
767 
768 	return 0;
769 }
770 
as21xxx_led_brightness_set(struct phy_device * phydev,u8 index,enum led_brightness value)771 static int as21xxx_led_brightness_set(struct phy_device *phydev,
772 				      u8 index, enum led_brightness value)
773 {
774 	u16 val = VEND1_LED_REG_A_EVENT_OFF;
775 
776 	if (index > AEON_MAX_LEDS)
777 		return -EINVAL;
778 
779 	if (value)
780 		val = VEND1_LED_REG_A_EVENT_ON;
781 
782 	return phy_modify_mmd(phydev, MDIO_MMD_VEND1,
783 			      VEND1_LED_REG(index),
784 			      VEND1_LED_REG_A_EVENT,
785 			      FIELD_PREP(VEND1_LED_REG_A_EVENT, val));
786 }
787 
as21xxx_led_hw_is_supported(struct phy_device * phydev,u8 index,unsigned long rules)788 static int as21xxx_led_hw_is_supported(struct phy_device *phydev, u8 index,
789 				       unsigned long rules)
790 {
791 	int i;
792 
793 	if (index > AEON_MAX_LEDS)
794 		return -EINVAL;
795 
796 	for (i = 0; i < ARRAY_SIZE(as21xxx_led_supported_pattern); i++)
797 		if (rules == as21xxx_led_supported_pattern[i].pattern)
798 			return 0;
799 
800 	return -EOPNOTSUPP;
801 }
802 
as21xxx_led_hw_control_get(struct phy_device * phydev,u8 index,unsigned long * rules)803 static int as21xxx_led_hw_control_get(struct phy_device *phydev, u8 index,
804 				      unsigned long *rules)
805 {
806 	int i, val;
807 
808 	if (index > AEON_MAX_LEDS)
809 		return -EINVAL;
810 
811 	val = phy_read_mmd(phydev, MDIO_MMD_VEND1, VEND1_LED_REG(index));
812 	if (val < 0)
813 		return val;
814 
815 	val = FIELD_GET(VEND1_LED_REG_A_EVENT, val);
816 	for (i = 0; i < ARRAY_SIZE(as21xxx_led_supported_pattern); i++)
817 		if (val == as21xxx_led_supported_pattern[i].val) {
818 			*rules = as21xxx_led_supported_pattern[i].pattern;
819 			return 0;
820 		}
821 
822 	/* Should be impossible */
823 	return -EINVAL;
824 }
825 
as21xxx_led_hw_control_set(struct phy_device * phydev,u8 index,unsigned long rules)826 static int as21xxx_led_hw_control_set(struct phy_device *phydev, u8 index,
827 				      unsigned long rules)
828 {
829 	u16 val = 0;
830 	int i;
831 
832 	if (index > AEON_MAX_LEDS)
833 		return -EINVAL;
834 
835 	for (i = 0; i < ARRAY_SIZE(as21xxx_led_supported_pattern); i++)
836 		if (rules == as21xxx_led_supported_pattern[i].pattern) {
837 			val = as21xxx_led_supported_pattern[i].val;
838 			break;
839 		}
840 
841 	return phy_modify_mmd(phydev, MDIO_MMD_VEND1,
842 			      VEND1_LED_REG(index),
843 			      VEND1_LED_REG_A_EVENT,
844 			      FIELD_PREP(VEND1_LED_REG_A_EVENT, val));
845 }
846 
as21xxx_led_polarity_set(struct phy_device * phydev,int index,unsigned long modes)847 static int as21xxx_led_polarity_set(struct phy_device *phydev, int index,
848 				    unsigned long modes)
849 {
850 	bool led_active_low = false;
851 	u16 mask, val = 0;
852 	u32 mode;
853 
854 	if (index > AEON_MAX_LEDS)
855 		return -EINVAL;
856 
857 	for_each_set_bit(mode, &modes, __PHY_LED_MODES_NUM) {
858 		switch (mode) {
859 		case PHY_LED_ACTIVE_LOW:
860 			led_active_low = true;
861 			break;
862 		case PHY_LED_ACTIVE_HIGH: /* default mode */
863 			led_active_low = false;
864 			break;
865 		default:
866 			return -EINVAL;
867 		}
868 	}
869 
870 	mask = VEND1_GLB_CPU_CTRL_LED_POLARITY(index);
871 	if (led_active_low)
872 		val = VEND1_GLB_CPU_CTRL_LED_POLARITY(index);
873 
874 	return phy_modify_mmd(phydev, MDIO_MMD_VEND1,
875 			      VEND1_GLB_REG_CPU_CTRL,
876 			      mask, val);
877 }
878 
as21xxx_match_phy_device(struct phy_device * phydev,const struct phy_driver * phydrv)879 static int as21xxx_match_phy_device(struct phy_device *phydev,
880 				    const struct phy_driver *phydrv)
881 {
882 	struct as21xxx_priv *priv;
883 	u16 ret_sts;
884 	u32 phy_id;
885 	int ret;
886 
887 	/* Skip PHY that are not AS21xxx or already have firmware loaded */
888 	if (phydev->c45_ids.device_ids[MDIO_MMD_PCS] != PHY_ID_AS21XXX)
889 		return genphy_match_phy_device(phydev, phydrv);
890 
891 	/* Read PHY ID to handle firmware just loaded */
892 	ret = phy_read_mmd(phydev, MDIO_MMD_PCS, MII_PHYSID1);
893 	if (ret < 0)
894 		return ret;
895 	phy_id = ret << 16;
896 
897 	ret = phy_read_mmd(phydev, MDIO_MMD_PCS, MII_PHYSID2);
898 	if (ret < 0)
899 		return ret;
900 	phy_id |= ret;
901 
902 	/* With PHY ID not the generic AS21xxx one assume
903 	 * the firmware just loaded
904 	 */
905 	if (phy_id != PHY_ID_AS21XXX)
906 		return phy_id == phydrv->phy_id;
907 
908 	/* Allocate temp priv and load the firmware */
909 	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
910 	if (!priv)
911 		return -ENOMEM;
912 
913 	mutex_init(&priv->ipc_lock);
914 
915 	ret = aeon_firmware_load(phydev);
916 	if (ret)
917 		goto out;
918 
919 	/* Sync parity... */
920 	ret = aeon_ipc_sync_parity(phydev, priv);
921 	if (ret)
922 		goto out;
923 
924 	/* ...and send a third NOOP cmd to wait for firmware finish loading */
925 	ret = aeon_ipc_noop(phydev, priv, &ret_sts);
926 	if (ret)
927 		goto out;
928 
929 out:
930 	mutex_destroy(&priv->ipc_lock);
931 	kfree(priv);
932 
933 	/* Return can either be 0 or a negative error code.
934 	 * Returning 0 here means THIS is NOT a suitable PHY.
935 	 *
936 	 * For the specific case of the generic Aeonsemi PHY ID that
937 	 * needs the firmware the be loaded first to have a correct PHY ID,
938 	 * this is OK as a matching PHY ID will be found right after.
939 	 * This relies on the driver probe order where the first PHY driver
940 	 * probed is the generic one.
941 	 */
942 	return ret;
943 }
944 
945 static struct phy_driver as21xxx_drivers[] = {
946 	{
947 		/* PHY expose in C45 as 0x7500 0x9410
948 		 * before firmware is loaded.
949 		 * This driver entry must be attempted first to load
950 		 * the firmware and thus update the ID registers.
951 		 */
952 		PHY_ID_MATCH_EXACT(PHY_ID_AS21XXX),
953 		.name		= "Aeonsemi AS21xxx",
954 		.match_phy_device = as21xxx_match_phy_device,
955 	},
956 	{
957 		PHY_ID_MATCH_EXACT(PHY_ID_AS21011JB1),
958 		.name		= "Aeonsemi AS21011JB1",
959 		.probe		= as21xxx_probe,
960 		.match_phy_device = as21xxx_match_phy_device,
961 		.read_status	= as21xxx_read_status,
962 		.led_brightness_set = as21xxx_led_brightness_set,
963 		.led_hw_is_supported = as21xxx_led_hw_is_supported,
964 		.led_hw_control_set = as21xxx_led_hw_control_set,
965 		.led_hw_control_get = as21xxx_led_hw_control_get,
966 		.led_polarity_set = as21xxx_led_polarity_set,
967 	},
968 	{
969 		PHY_ID_MATCH_EXACT(PHY_ID_AS21011PB1),
970 		.name		= "Aeonsemi AS21011PB1",
971 		.probe		= as21xxx_probe,
972 		.match_phy_device = as21xxx_match_phy_device,
973 		.read_status	= as21xxx_read_status,
974 		.led_brightness_set = as21xxx_led_brightness_set,
975 		.led_hw_is_supported = as21xxx_led_hw_is_supported,
976 		.led_hw_control_set = as21xxx_led_hw_control_set,
977 		.led_hw_control_get = as21xxx_led_hw_control_get,
978 		.led_polarity_set = as21xxx_led_polarity_set,
979 	},
980 	{
981 		PHY_ID_MATCH_EXACT(PHY_ID_AS21010PB1),
982 		.name		= "Aeonsemi AS21010PB1",
983 		.probe		= as21xxx_probe,
984 		.match_phy_device = as21xxx_match_phy_device,
985 		.read_status	= as21xxx_read_status,
986 		.led_brightness_set = as21xxx_led_brightness_set,
987 		.led_hw_is_supported = as21xxx_led_hw_is_supported,
988 		.led_hw_control_set = as21xxx_led_hw_control_set,
989 		.led_hw_control_get = as21xxx_led_hw_control_get,
990 		.led_polarity_set = as21xxx_led_polarity_set,
991 	},
992 	{
993 		PHY_ID_MATCH_EXACT(PHY_ID_AS21010JB1),
994 		.name		= "Aeonsemi AS21010JB1",
995 		.probe		= as21xxx_probe,
996 		.match_phy_device = as21xxx_match_phy_device,
997 		.read_status	= as21xxx_read_status,
998 		.led_brightness_set = as21xxx_led_brightness_set,
999 		.led_hw_is_supported = as21xxx_led_hw_is_supported,
1000 		.led_hw_control_set = as21xxx_led_hw_control_set,
1001 		.led_hw_control_get = as21xxx_led_hw_control_get,
1002 		.led_polarity_set = as21xxx_led_polarity_set,
1003 	},
1004 	{
1005 		PHY_ID_MATCH_EXACT(PHY_ID_AS21210PB1),
1006 		.name		= "Aeonsemi AS21210PB1",
1007 		.probe		= as21xxx_probe,
1008 		.match_phy_device = as21xxx_match_phy_device,
1009 		.read_status	= as21xxx_read_status,
1010 		.led_brightness_set = as21xxx_led_brightness_set,
1011 		.led_hw_is_supported = as21xxx_led_hw_is_supported,
1012 		.led_hw_control_set = as21xxx_led_hw_control_set,
1013 		.led_hw_control_get = as21xxx_led_hw_control_get,
1014 		.led_polarity_set = as21xxx_led_polarity_set,
1015 	},
1016 	{
1017 		PHY_ID_MATCH_EXACT(PHY_ID_AS21510JB1),
1018 		.name		= "Aeonsemi AS21510JB1",
1019 		.probe		= as21xxx_probe,
1020 		.match_phy_device = as21xxx_match_phy_device,
1021 		.read_status	= as21xxx_read_status,
1022 		.led_brightness_set = as21xxx_led_brightness_set,
1023 		.led_hw_is_supported = as21xxx_led_hw_is_supported,
1024 		.led_hw_control_set = as21xxx_led_hw_control_set,
1025 		.led_hw_control_get = as21xxx_led_hw_control_get,
1026 		.led_polarity_set = as21xxx_led_polarity_set,
1027 	},
1028 	{
1029 		PHY_ID_MATCH_EXACT(PHY_ID_AS21510PB1),
1030 		.name		= "Aeonsemi AS21510PB1",
1031 		.probe		= as21xxx_probe,
1032 		.match_phy_device = as21xxx_match_phy_device,
1033 		.read_status	= as21xxx_read_status,
1034 		.led_brightness_set = as21xxx_led_brightness_set,
1035 		.led_hw_is_supported = as21xxx_led_hw_is_supported,
1036 		.led_hw_control_set = as21xxx_led_hw_control_set,
1037 		.led_hw_control_get = as21xxx_led_hw_control_get,
1038 		.led_polarity_set = as21xxx_led_polarity_set,
1039 	},
1040 	{
1041 		PHY_ID_MATCH_EXACT(PHY_ID_AS21511JB1),
1042 		.name		= "Aeonsemi AS21511JB1",
1043 		.probe		= as21xxx_probe,
1044 		.match_phy_device = as21xxx_match_phy_device,
1045 		.read_status	= as21xxx_read_status,
1046 		.led_brightness_set = as21xxx_led_brightness_set,
1047 		.led_hw_is_supported = as21xxx_led_hw_is_supported,
1048 		.led_hw_control_set = as21xxx_led_hw_control_set,
1049 		.led_hw_control_get = as21xxx_led_hw_control_get,
1050 		.led_polarity_set = as21xxx_led_polarity_set,
1051 	},
1052 	{
1053 		PHY_ID_MATCH_EXACT(PHY_ID_AS21210JB1),
1054 		.name		= "Aeonsemi AS21210JB1",
1055 		.probe		= as21xxx_probe,
1056 		.match_phy_device = as21xxx_match_phy_device,
1057 		.read_status	= as21xxx_read_status,
1058 		.led_brightness_set = as21xxx_led_brightness_set,
1059 		.led_hw_is_supported = as21xxx_led_hw_is_supported,
1060 		.led_hw_control_set = as21xxx_led_hw_control_set,
1061 		.led_hw_control_get = as21xxx_led_hw_control_get,
1062 		.led_polarity_set = as21xxx_led_polarity_set,
1063 	},
1064 	{
1065 		PHY_ID_MATCH_EXACT(PHY_ID_AS21511PB1),
1066 		.name		= "Aeonsemi AS21511PB1",
1067 		.probe		= as21xxx_probe,
1068 		.match_phy_device = as21xxx_match_phy_device,
1069 		.read_status	= as21xxx_read_status,
1070 		.led_brightness_set = as21xxx_led_brightness_set,
1071 		.led_hw_is_supported = as21xxx_led_hw_is_supported,
1072 		.led_hw_control_set = as21xxx_led_hw_control_set,
1073 		.led_hw_control_get = as21xxx_led_hw_control_get,
1074 		.led_polarity_set = as21xxx_led_polarity_set,
1075 	},
1076 };
1077 module_phy_driver(as21xxx_drivers);
1078 
1079 static struct mdio_device_id __maybe_unused as21xxx_tbl[] = {
1080 	{ PHY_ID_MATCH_VENDOR(PHY_VENDOR_AEONSEMI) },
1081 	{ }
1082 };
1083 MODULE_DEVICE_TABLE(mdio, as21xxx_tbl);
1084 
1085 MODULE_DESCRIPTION("Aeonsemi AS21xxx PHY driver");
1086 MODULE_AUTHOR("Christian Marangi <ansuelsmth@gmail.com>");
1087 MODULE_LICENSE("GPL");
1088