Merge branch 'parisc-5.1-1' of git://git.kernel.org/pub/scm/linux/kernel/git/deller...
[sfrench/cifs-2.6.git] / drivers / net / phy / cortina.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  *    Copyright 2017 NXP
4  *
5  *    CORTINA is a registered trademark of Cortina Systems, Inc.
6  *
7  */
8 #include <linux/module.h>
9 #include <linux/phy.h>
10
11 #define PHY_ID_CS4340   0x13e51002
12
13 #define VILLA_GLOBAL_CHIP_ID_LSB                        0x0
14 #define VILLA_GLOBAL_CHIP_ID_MSB                        0x1
15
16 #define VILLA_GLOBAL_GPIO_1_INTS                        0x017
17
18 static int cortina_read_reg(struct phy_device *phydev, u16 regnum)
19 {
20         return mdiobus_read(phydev->mdio.bus, phydev->mdio.addr,
21                             MII_ADDR_C45 | regnum);
22 }
23
24 static int cortina_read_status(struct phy_device *phydev)
25 {
26         int gpio_int_status, ret = 0;
27
28         gpio_int_status = cortina_read_reg(phydev, VILLA_GLOBAL_GPIO_1_INTS);
29         if (gpio_int_status < 0) {
30                 ret = gpio_int_status;
31                 goto err;
32         }
33
34         if (gpio_int_status & 0x8) {
35                 /* up when edc_convergedS set */
36                 phydev->speed = SPEED_10000;
37                 phydev->duplex = DUPLEX_FULL;
38                 phydev->link = 1;
39         } else {
40                 phydev->link = 0;
41         }
42
43 err:
44         return ret;
45 }
46
47 static int cortina_probe(struct phy_device *phydev)
48 {
49         u32 phy_id = 0;
50         int id_lsb = 0, id_msb = 0;
51
52         /* Read device id from phy registers. */
53         id_lsb = cortina_read_reg(phydev, VILLA_GLOBAL_CHIP_ID_LSB);
54         if (id_lsb < 0)
55                 return -ENXIO;
56
57         phy_id = id_lsb << 16;
58
59         id_msb = cortina_read_reg(phydev, VILLA_GLOBAL_CHIP_ID_MSB);
60         if (id_msb < 0)
61                 return -ENXIO;
62
63         phy_id |= id_msb;
64
65         /* Make sure the device tree binding matched the driver with the
66          * right device.
67          */
68         if (phy_id != phydev->drv->phy_id) {
69                 phydev_err(phydev, "Error matching phy with %s driver\n",
70                            phydev->drv->name);
71                 return -ENODEV;
72         }
73
74         return 0;
75 }
76
77 static struct phy_driver cortina_driver[] = {
78 {
79         .phy_id         = PHY_ID_CS4340,
80         .phy_id_mask    = 0xffffffff,
81         .name           = "Cortina CS4340",
82         .features       = PHY_10GBIT_FEATURES,
83         .config_aneg    = gen10g_config_aneg,
84         .read_status    = cortina_read_status,
85         .soft_reset     = genphy_no_soft_reset,
86         .probe          = cortina_probe,
87 },
88 };
89
90 module_phy_driver(cortina_driver);
91
92 static struct mdio_device_id __maybe_unused cortina_tbl[] = {
93         { PHY_ID_CS4340, 0xffffffff},
94         {},
95 };
96
97 MODULE_DEVICE_TABLE(mdio, cortina_tbl);
98
99 MODULE_DESCRIPTION("Cortina EDC CDR 10G Ethernet PHY driver");
100 MODULE_AUTHOR("NXP");
101 MODULE_LICENSE("GPL");