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