Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0+
0002 /*
0003  *    Copyright 2017 NXP
0004  *
0005  *    CORTINA is a registered trademark of Cortina Systems, Inc.
0006  *
0007  */
0008 #include <linux/module.h>
0009 #include <linux/phy.h>
0010 
0011 #define PHY_ID_CS4340   0x13e51002
0012 
0013 #define VILLA_GLOBAL_CHIP_ID_LSB            0x0
0014 #define VILLA_GLOBAL_CHIP_ID_MSB            0x1
0015 
0016 #define VILLA_GLOBAL_GPIO_1_INTS            0x017
0017 
0018 static int cortina_read_reg(struct phy_device *phydev, u16 regnum)
0019 {
0020     return mdiobus_c45_read(phydev->mdio.bus, phydev->mdio.addr, 0, regnum);
0021 }
0022 
0023 static int cortina_read_status(struct phy_device *phydev)
0024 {
0025     int gpio_int_status, ret = 0;
0026 
0027     gpio_int_status = cortina_read_reg(phydev, VILLA_GLOBAL_GPIO_1_INTS);
0028     if (gpio_int_status < 0) {
0029         ret = gpio_int_status;
0030         goto err;
0031     }
0032 
0033     if (gpio_int_status & 0x8) {
0034         /* up when edc_convergedS set */
0035         phydev->speed = SPEED_10000;
0036         phydev->duplex = DUPLEX_FULL;
0037         phydev->link = 1;
0038     } else {
0039         phydev->link = 0;
0040     }
0041 
0042 err:
0043     return ret;
0044 }
0045 
0046 static int cortina_probe(struct phy_device *phydev)
0047 {
0048     u32 phy_id = 0;
0049     int id_lsb = 0, id_msb = 0;
0050 
0051     /* Read device id from phy registers. */
0052     id_lsb = cortina_read_reg(phydev, VILLA_GLOBAL_CHIP_ID_LSB);
0053     if (id_lsb < 0)
0054         return -ENXIO;
0055 
0056     phy_id = id_lsb << 16;
0057 
0058     id_msb = cortina_read_reg(phydev, VILLA_GLOBAL_CHIP_ID_MSB);
0059     if (id_msb < 0)
0060         return -ENXIO;
0061 
0062     phy_id |= id_msb;
0063 
0064     /* Make sure the device tree binding matched the driver with the
0065      * right device.
0066      */
0067     if (phy_id != phydev->drv->phy_id) {
0068         phydev_err(phydev, "Error matching phy with %s driver\n",
0069                phydev->drv->name);
0070         return -ENODEV;
0071     }
0072 
0073     return 0;
0074 }
0075 
0076 static struct phy_driver cortina_driver[] = {
0077 {
0078     .phy_id     = PHY_ID_CS4340,
0079     .phy_id_mask    = 0xffffffff,
0080     .name       = "Cortina CS4340",
0081     .features       = PHY_10GBIT_FEATURES,
0082     .config_aneg    = gen10g_config_aneg,
0083     .read_status    = cortina_read_status,
0084     .probe      = cortina_probe,
0085 },
0086 };
0087 
0088 module_phy_driver(cortina_driver);
0089 
0090 static struct mdio_device_id __maybe_unused cortina_tbl[] = {
0091     { PHY_ID_CS4340, 0xffffffff},
0092     {},
0093 };
0094 
0095 MODULE_DEVICE_TABLE(mdio, cortina_tbl);
0096 
0097 MODULE_DESCRIPTION("Cortina EDC CDR 10G Ethernet PHY driver");
0098 MODULE_AUTHOR("NXP");
0099 MODULE_LICENSE("GPL");