1 /* 2 * Copyright 2017 NXP 3 * 4 * This program is free software; you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License as published by 6 * the Free Software Foundation; either version 2 of the License, or 7 * (at your option) any later version. 8 * 9 * This program is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 * 14 * CORTINA is a registered trademark of Cortina Systems, Inc. 15 * 16 */ 17 #include <linux/module.h> 18 #include <linux/phy.h> 19 20 #define PHY_ID_CS4340 0x13e51002 21 22 #define VILLA_GLOBAL_CHIP_ID_LSB 0x0 23 #define VILLA_GLOBAL_CHIP_ID_MSB 0x1 24 25 #define VILLA_GLOBAL_GPIO_1_INTS 0x017 26 27 static int cortina_read_reg(struct phy_device *phydev, u16 regnum) 28 { 29 return mdiobus_read(phydev->mdio.bus, phydev->mdio.addr, 30 MII_ADDR_C45 | regnum); 31 } 32 33 static int cortina_config_aneg(struct phy_device *phydev) 34 { 35 phydev->supported = SUPPORTED_10000baseT_Full; 36 phydev->advertising = SUPPORTED_10000baseT_Full; 37 38 return 0; 39 } 40 41 static int cortina_read_status(struct phy_device *phydev) 42 { 43 int gpio_int_status, ret = 0; 44 45 gpio_int_status = cortina_read_reg(phydev, VILLA_GLOBAL_GPIO_1_INTS); 46 if (gpio_int_status < 0) { 47 ret = gpio_int_status; 48 goto err; 49 } 50 51 if (gpio_int_status & 0x8) { 52 /* up when edc_convergedS set */ 53 phydev->speed = SPEED_10000; 54 phydev->duplex = DUPLEX_FULL; 55 phydev->link = 1; 56 } else { 57 phydev->link = 0; 58 } 59 60 err: 61 return ret; 62 } 63 64 static int cortina_soft_reset(struct phy_device *phydev) 65 { 66 return 0; 67 } 68 69 static int cortina_probe(struct phy_device *phydev) 70 { 71 u32 phy_id = 0; 72 int id_lsb = 0, id_msb = 0; 73 74 /* Read device id from phy registers. */ 75 id_lsb = cortina_read_reg(phydev, VILLA_GLOBAL_CHIP_ID_LSB); 76 if (id_lsb < 0) 77 return -ENXIO; 78 79 phy_id = id_lsb << 16; 80 81 id_msb = cortina_read_reg(phydev, VILLA_GLOBAL_CHIP_ID_MSB); 82 if (id_msb < 0) 83 return -ENXIO; 84 85 phy_id |= id_msb; 86 87 /* Make sure the device tree binding matched the driver with the 88 * right device. 89 */ 90 if (phy_id != phydev->drv->phy_id) { 91 phydev_err(phydev, "Error matching phy with %s driver\n", 92 phydev->drv->name); 93 return -ENODEV; 94 } 95 96 return 0; 97 } 98 99 static struct phy_driver cortina_driver[] = { 100 { 101 .phy_id = PHY_ID_CS4340, 102 .phy_id_mask = 0xffffffff, 103 .name = "Cortina CS4340", 104 .config_aneg = cortina_config_aneg, 105 .read_status = cortina_read_status, 106 .soft_reset = cortina_soft_reset, 107 .probe = cortina_probe, 108 }, 109 }; 110 111 module_phy_driver(cortina_driver); 112 113 static struct mdio_device_id __maybe_unused cortina_tbl[] = { 114 { PHY_ID_CS4340, 0xffffffff}, 115 {}, 116 }; 117 118 MODULE_DEVICE_TABLE(mdio, cortina_tbl); 119