1 // SPDX-License-Identifier: GPL-2.0
2 // Copyright (C) 2018 Microchip Technology
4 #include <linux/kernel.h>
5 #include <linux/module.h>
6 #include <linux/delay.h>
9 #include <linux/ethtool.h>
10 #include <linux/ethtool_netlink.h>
12 /* External Register Control Register */
13 #define LAN87XX_EXT_REG_CTL (0x14)
14 #define LAN87XX_EXT_REG_CTL_RD_CTL (0x1000)
15 #define LAN87XX_EXT_REG_CTL_WR_CTL (0x0800)
17 /* External Register Read Data Register */
18 #define LAN87XX_EXT_REG_RD_DATA (0x15)
20 /* External Register Write Data Register */
21 #define LAN87XX_EXT_REG_WR_DATA (0x16)
23 /* Interrupt Source Register */
24 #define LAN87XX_INTERRUPT_SOURCE (0x18)
26 /* Interrupt Mask Register */
27 #define LAN87XX_INTERRUPT_MASK (0x19)
28 #define LAN87XX_MASK_LINK_UP (0x0004)
29 #define LAN87XX_MASK_LINK_DOWN (0x0002)
31 /* MISC Control 1 Register */
32 #define LAN87XX_CTRL_1 (0x11)
33 #define LAN87XX_MASK_RGMII_TXC_DLY_EN (0x4000)
34 #define LAN87XX_MASK_RGMII_RXC_DLY_EN (0x2000)
36 /* phyaccess nested types */
37 #define PHYACC_ATTR_MODE_READ 0
38 #define PHYACC_ATTR_MODE_WRITE 1
39 #define PHYACC_ATTR_MODE_MODIFY 2
41 #define PHYACC_ATTR_BANK_SMI 0
42 #define PHYACC_ATTR_BANK_MISC 1
43 #define PHYACC_ATTR_BANK_PCS 2
44 #define PHYACC_ATTR_BANK_AFE 3
45 #define PHYACC_ATTR_BANK_DSP 4
46 #define PHYACC_ATTR_BANK_MAX 7
48 /* measurement defines */
49 #define LAN87XX_CABLE_TEST_OK 0
50 #define LAN87XX_CABLE_TEST_OPEN 1
51 #define LAN87XX_CABLE_TEST_SAME_SHORT 2
53 #define DRIVER_AUTHOR "Nisar Sayed <nisar.sayed@microchip.com>"
54 #define DRIVER_DESC "Microchip LAN87XX T1 PHY driver"
56 struct access_ereg_val {
64 static int access_ereg(struct phy_device *phydev, u8 mode, u8 bank,
70 if (mode > PHYACC_ATTR_MODE_WRITE || bank > PHYACC_ATTR_BANK_MAX)
73 if (bank == PHYACC_ATTR_BANK_SMI) {
74 if (mode == PHYACC_ATTR_MODE_WRITE)
75 rc = phy_write(phydev, offset, val);
77 rc = phy_read(phydev, offset);
81 if (mode == PHYACC_ATTR_MODE_WRITE) {
82 ereg = LAN87XX_EXT_REG_CTL_WR_CTL;
83 rc = phy_write(phydev, LAN87XX_EXT_REG_WR_DATA, val);
87 ereg = LAN87XX_EXT_REG_CTL_RD_CTL;
90 ereg |= (bank << 8) | offset;
92 rc = phy_write(phydev, LAN87XX_EXT_REG_CTL, ereg);
96 if (mode == PHYACC_ATTR_MODE_READ)
97 rc = phy_read(phydev, LAN87XX_EXT_REG_RD_DATA);
102 static int access_ereg_modify_changed(struct phy_device *phydev,
103 u8 bank, u8 offset, u16 val, u16 mask)
107 if (bank > PHYACC_ATTR_BANK_MAX)
110 rc = access_ereg(phydev, PHYACC_ATTR_MODE_READ, bank, offset, val);
114 new = val | (rc & (mask ^ 0xFFFF));
115 rc = access_ereg(phydev, PHYACC_ATTR_MODE_WRITE, bank, offset, new);
120 static int lan87xx_config_rgmii_delay(struct phy_device *phydev)
124 if (!phy_interface_is_rgmii(phydev))
127 rc = access_ereg(phydev, PHYACC_ATTR_MODE_READ,
128 PHYACC_ATTR_BANK_MISC, LAN87XX_CTRL_1, 0);
132 switch (phydev->interface) {
133 case PHY_INTERFACE_MODE_RGMII:
134 rc &= ~LAN87XX_MASK_RGMII_TXC_DLY_EN;
135 rc &= ~LAN87XX_MASK_RGMII_RXC_DLY_EN;
137 case PHY_INTERFACE_MODE_RGMII_ID:
138 rc |= LAN87XX_MASK_RGMII_TXC_DLY_EN;
139 rc |= LAN87XX_MASK_RGMII_RXC_DLY_EN;
141 case PHY_INTERFACE_MODE_RGMII_RXID:
142 rc &= ~LAN87XX_MASK_RGMII_TXC_DLY_EN;
143 rc |= LAN87XX_MASK_RGMII_RXC_DLY_EN;
145 case PHY_INTERFACE_MODE_RGMII_TXID:
146 rc |= LAN87XX_MASK_RGMII_TXC_DLY_EN;
147 rc &= ~LAN87XX_MASK_RGMII_RXC_DLY_EN;
153 return access_ereg(phydev, PHYACC_ATTR_MODE_WRITE,
154 PHYACC_ATTR_BANK_MISC, LAN87XX_CTRL_1, rc);
157 static int lan87xx_phy_init(struct phy_device *phydev)
159 static const struct access_ereg_val init[] = {
160 /* TX Amplitude = 5 */
161 {PHYACC_ATTR_MODE_MODIFY, PHYACC_ATTR_BANK_AFE, 0x0B,
163 /* Clear SMI interrupts */
164 {PHYACC_ATTR_MODE_READ, PHYACC_ATTR_BANK_SMI, 0x18,
166 /* Clear MISC interrupts */
167 {PHYACC_ATTR_MODE_READ, PHYACC_ATTR_BANK_MISC, 0x08,
169 /* Turn on TC10 Ring Oscillator (ROSC) */
170 {PHYACC_ATTR_MODE_MODIFY, PHYACC_ATTR_BANK_MISC, 0x20,
172 /* WUR Detect Length to 1.2uS, LPC Detect Length to 1.09uS */
173 {PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_PCS, 0x20,
175 /* Wake_In Debounce Length to 39uS, Wake_Out Length to 79uS */
176 {PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_MISC, 0x21,
178 /* Enable Auto Wake Forward to Wake_Out, ROSC on, Sleep,
179 * and Wake_In to wake PHY
181 {PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_MISC, 0x20,
183 /* Enable WUP Auto Fwd, Enable Wake on MDI, Wakeup Debouncer
186 {PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_MISC, 0x24,
189 {PHYACC_ATTR_MODE_MODIFY, PHYACC_ATTR_BANK_SMI, 0x1A,
194 /* Start manual initialization procedures in Managed Mode */
195 rc = access_ereg_modify_changed(phydev, PHYACC_ATTR_BANK_SMI,
196 0x1a, 0x0000, 0x0100);
200 /* Soft Reset the SMI block */
201 rc = access_ereg_modify_changed(phydev, PHYACC_ATTR_BANK_SMI,
202 0x00, 0x8000, 0x8000);
206 /* Check to see if the self-clearing bit is cleared */
207 usleep_range(1000, 2000);
208 rc = access_ereg(phydev, PHYACC_ATTR_MODE_READ,
209 PHYACC_ATTR_BANK_SMI, 0x00, 0);
212 if ((rc & 0x8000) != 0)
215 /* PHY Initialization */
216 for (i = 0; i < ARRAY_SIZE(init); i++) {
217 if (init[i].mode == PHYACC_ATTR_MODE_MODIFY) {
218 rc = access_ereg_modify_changed(phydev, init[i].bank,
223 rc = access_ereg(phydev, init[i].mode, init[i].bank,
224 init[i].offset, init[i].val);
230 return lan87xx_config_rgmii_delay(phydev);
233 static int lan87xx_phy_config_intr(struct phy_device *phydev)
237 if (phydev->interrupts == PHY_INTERRUPT_ENABLED) {
238 /* unmask all source and clear them before enable */
239 rc = phy_write(phydev, LAN87XX_INTERRUPT_MASK, 0x7FFF);
240 rc = phy_read(phydev, LAN87XX_INTERRUPT_SOURCE);
241 val = LAN87XX_MASK_LINK_UP | LAN87XX_MASK_LINK_DOWN;
242 rc = phy_write(phydev, LAN87XX_INTERRUPT_MASK, val);
244 rc = phy_write(phydev, LAN87XX_INTERRUPT_MASK, val);
248 rc = phy_read(phydev, LAN87XX_INTERRUPT_SOURCE);
251 return rc < 0 ? rc : 0;
254 static irqreturn_t lan87xx_handle_interrupt(struct phy_device *phydev)
258 irq_status = phy_read(phydev, LAN87XX_INTERRUPT_SOURCE);
259 if (irq_status < 0) {
267 phy_trigger_machine(phydev);
272 static int lan87xx_config_init(struct phy_device *phydev)
274 int rc = lan87xx_phy_init(phydev);
276 return rc < 0 ? rc : 0;
279 static int microchip_cable_test_start_common(struct phy_device *phydev)
283 /* If auto-negotiation is enabled, but not complete, the cable
284 * test never completes. So disable auto-neg.
286 bmcr = phy_read(phydev, MII_BMCR);
290 bmsr = phy_read(phydev, MII_BMSR);
295 if (bmcr & BMCR_ANENABLE) {
296 ret = phy_modify(phydev, MII_BMCR, BMCR_ANENABLE, 0);
299 ret = genphy_soft_reset(phydev);
304 /* If the link is up, allow it some time to go down */
305 if (bmsr & BMSR_LSTATUS)
311 static int lan87xx_cable_test_start(struct phy_device *phydev)
313 static const struct access_ereg_val cable_test[] = {
315 {PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_DSP, 93,
318 {PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_DSP, 94,
321 {PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_DSP, 95,
323 /* cable diag thresh */
324 {PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_DSP, 92,
327 {PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_DSP, 79,
329 /* clock align for each iteration */
330 {PHYACC_ATTR_MODE_MODIFY, PHYACC_ATTR_BANK_DSP, 55,
332 /* max cycle wait config */
333 {PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_DSP, 94,
335 /* start cable diag*/
336 {PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_DSP, 90,
341 rc = microchip_cable_test_start_common(phydev);
345 /* start cable diag */
346 /* check if part is alive - if not, return diagnostic error */
347 rc = access_ereg(phydev, PHYACC_ATTR_MODE_READ, PHYACC_ATTR_BANK_SMI,
352 /* master/slave specific configs */
353 rc = access_ereg(phydev, PHYACC_ATTR_MODE_READ, PHYACC_ATTR_BANK_SMI,
358 if ((rc & 0x4000) != 0x4000) {
360 rc = access_ereg_modify_changed(phydev, PHYACC_ATTR_BANK_AFE,
364 rc = access_ereg_modify_changed(phydev, PHYACC_ATTR_BANK_SMI,
370 rc = access_ereg_modify_changed(phydev, PHYACC_ATTR_BANK_SMI,
376 for (i = 0; i < ARRAY_SIZE(cable_test); i++) {
377 if (cable_test[i].mode == PHYACC_ATTR_MODE_MODIFY) {
378 rc = access_ereg_modify_changed(phydev,
380 cable_test[i].offset,
386 rc = access_ereg(phydev, cable_test[i].mode,
388 cable_test[i].offset,
394 /* cable diag started */
399 static int lan87xx_cable_test_report_trans(u32 result)
402 case LAN87XX_CABLE_TEST_OK:
403 return ETHTOOL_A_CABLE_RESULT_CODE_OK;
404 case LAN87XX_CABLE_TEST_OPEN:
405 return ETHTOOL_A_CABLE_RESULT_CODE_OPEN;
406 case LAN87XX_CABLE_TEST_SAME_SHORT:
407 return ETHTOOL_A_CABLE_RESULT_CODE_SAME_SHORT;
409 /* DIAGNOSTIC_ERROR */
410 return ETHTOOL_A_CABLE_RESULT_CODE_UNSPEC;
414 static int lan87xx_cable_test_report(struct phy_device *phydev)
416 int pos_peak_cycle = 0, pos_peak_in_phases = 0, pos_peak_phase = 0;
417 int neg_peak_cycle = 0, neg_peak_in_phases = 0, neg_peak_phase = 0;
418 int noise_margin = 20, time_margin = 89, jitter_var = 30;
419 int min_time_diff = 96, max_time_diff = 96 + time_margin;
420 bool fault = false, check_a = false, check_b = false;
421 int gain_idx = 0, pos_peak = 0, neg_peak = 0;
422 int pos_peak_time = 0, neg_peak_time = 0;
423 int pos_peak_in_phases_hybrid = 0;
426 gain_idx = access_ereg(phydev, PHYACC_ATTR_MODE_READ,
427 PHYACC_ATTR_BANK_DSP, 151, 0);
428 /* read non-hybrid results */
429 pos_peak = access_ereg(phydev, PHYACC_ATTR_MODE_READ,
430 PHYACC_ATTR_BANK_DSP, 153, 0);
431 neg_peak = access_ereg(phydev, PHYACC_ATTR_MODE_READ,
432 PHYACC_ATTR_BANK_DSP, 154, 0);
433 pos_peak_time = access_ereg(phydev, PHYACC_ATTR_MODE_READ,
434 PHYACC_ATTR_BANK_DSP, 156, 0);
435 neg_peak_time = access_ereg(phydev, PHYACC_ATTR_MODE_READ,
436 PHYACC_ATTR_BANK_DSP, 157, 0);
438 pos_peak_cycle = (pos_peak_time >> 7) & 0x7F;
439 /* calculate non-hybrid values */
440 pos_peak_phase = pos_peak_time & 0x7F;
441 pos_peak_in_phases = (pos_peak_cycle * 96) + pos_peak_phase;
442 neg_peak_cycle = (neg_peak_time >> 7) & 0x7F;
443 neg_peak_phase = neg_peak_time & 0x7F;
444 neg_peak_in_phases = (neg_peak_cycle * 96) + neg_peak_phase;
448 ((pos_peak_in_phases - neg_peak_in_phases) >= min_time_diff) &&
449 ((pos_peak_in_phases - neg_peak_in_phases) < max_time_diff) &&
450 pos_peak_in_phases_hybrid < pos_peak_in_phases &&
451 (pos_peak_in_phases_hybrid < (neg_peak_in_phases + jitter_var));
453 ((neg_peak_in_phases - pos_peak_in_phases) >= min_time_diff) &&
454 ((neg_peak_in_phases - pos_peak_in_phases) < max_time_diff) &&
455 pos_peak_in_phases_hybrid < neg_peak_in_phases &&
456 (pos_peak_in_phases_hybrid < (pos_peak_in_phases + jitter_var));
458 if (pos_peak_in_phases > neg_peak_in_phases && check_a)
460 else if ((neg_peak_in_phases > pos_peak_in_phases) && check_b)
463 if (pos_peak > noise_margin && neg_peak > noise_margin &&
465 if (detect == 1 || detect == 2)
472 ethnl_cable_test_result(phydev, ETHTOOL_A_CABLE_PAIR_A,
473 lan87xx_cable_test_report_trans(detect));
478 static int lan87xx_cable_test_get_status(struct phy_device *phydev,
485 /* check if cable diag was finished */
486 rc = access_ereg(phydev, PHYACC_ATTR_MODE_READ, PHYACC_ATTR_BANK_DSP,
493 rc = access_ereg(phydev, PHYACC_ATTR_MODE_WRITE,
494 PHYACC_ATTR_BANK_DSP,
501 return lan87xx_cable_test_report(phydev);
507 static struct phy_driver microchip_t1_phy_driver[] = {
509 .phy_id = 0x0007c150,
510 .phy_id_mask = 0xfffffff0,
511 .name = "Microchip LAN87xx T1",
512 .flags = PHY_POLL_CABLE_TEST,
514 .features = PHY_BASIC_T1_FEATURES,
516 .config_init = lan87xx_config_init,
518 .config_intr = lan87xx_phy_config_intr,
519 .handle_interrupt = lan87xx_handle_interrupt,
521 .suspend = genphy_suspend,
522 .resume = genphy_resume,
523 .cable_test_start = lan87xx_cable_test_start,
524 .cable_test_get_status = lan87xx_cable_test_get_status,
528 module_phy_driver(microchip_t1_phy_driver);
530 static struct mdio_device_id __maybe_unused microchip_t1_tbl[] = {
531 { 0x0007c150, 0xfffffff0 },
535 MODULE_DEVICE_TABLE(mdio, microchip_t1_tbl);
537 MODULE_AUTHOR(DRIVER_AUTHOR);
538 MODULE_DESCRIPTION(DRIVER_DESC);
539 MODULE_LICENSE("GPL");