1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Copyright (c) 2010 ASIX Electronics Corporation 4 * Copyright (c) 2020 Samsung Electronics Co., Ltd. 5 * 6 * ASIX AX88796C SPI Fast Ethernet Linux driver 7 */ 8 9 #define pr_fmt(fmt) "ax88796c: " fmt 10 11 #include <linux/bitmap.h> 12 #include <linux/iopoll.h> 13 #include <linux/phy.h> 14 #include <linux/netdevice.h> 15 16 #include "ax88796c_main.h" 17 #include "ax88796c_ioctl.h" 18 19 static const char ax88796c_priv_flag_names[][ETH_GSTRING_LEN] = { 20 "SPICompression", 21 }; 22 23 static void 24 ax88796c_get_drvinfo(struct net_device *ndev, struct ethtool_drvinfo *info) 25 { 26 /* Inherit standard device info */ 27 strscpy(info->driver, DRV_NAME, sizeof(info->driver)); 28 } 29 30 static u32 ax88796c_get_msglevel(struct net_device *ndev) 31 { 32 struct ax88796c_device *ax_local = to_ax88796c_device(ndev); 33 34 return ax_local->msg_enable; 35 } 36 37 static void ax88796c_set_msglevel(struct net_device *ndev, u32 level) 38 { 39 struct ax88796c_device *ax_local = to_ax88796c_device(ndev); 40 41 ax_local->msg_enable = level; 42 } 43 44 static void 45 ax88796c_get_pauseparam(struct net_device *ndev, struct ethtool_pauseparam *pause) 46 { 47 struct ax88796c_device *ax_local = to_ax88796c_device(ndev); 48 49 pause->tx_pause = !!(ax_local->flowctrl & AX_FC_TX); 50 pause->rx_pause = !!(ax_local->flowctrl & AX_FC_RX); 51 pause->autoneg = (ax_local->flowctrl & AX_FC_ANEG) ? 52 AUTONEG_ENABLE : 53 AUTONEG_DISABLE; 54 } 55 56 static int 57 ax88796c_set_pauseparam(struct net_device *ndev, struct ethtool_pauseparam *pause) 58 { 59 struct ax88796c_device *ax_local = to_ax88796c_device(ndev); 60 int fc; 61 62 /* The following logic comes from phylink_ethtool_set_pauseparam() */ 63 fc = pause->tx_pause ? AX_FC_TX : 0; 64 fc |= pause->rx_pause ? AX_FC_RX : 0; 65 fc |= pause->autoneg ? AX_FC_ANEG : 0; 66 67 ax_local->flowctrl = fc; 68 69 if (pause->autoneg) { 70 phy_set_asym_pause(ax_local->phydev, pause->tx_pause, 71 pause->rx_pause); 72 } else { 73 int maccr = 0; 74 75 phy_set_asym_pause(ax_local->phydev, 0, 0); 76 maccr |= (ax_local->flowctrl & AX_FC_RX) ? MACCR_RXFC_ENABLE : 0; 77 maccr |= (ax_local->flowctrl & AX_FC_TX) ? MACCR_TXFC_ENABLE : 0; 78 79 mutex_lock(&ax_local->spi_lock); 80 81 maccr |= AX_READ(&ax_local->ax_spi, P0_MACCR) & 82 ~(MACCR_TXFC_ENABLE | MACCR_RXFC_ENABLE); 83 AX_WRITE(&ax_local->ax_spi, maccr, P0_MACCR); 84 85 mutex_unlock(&ax_local->spi_lock); 86 } 87 88 return 0; 89 } 90 91 static int ax88796c_get_regs_len(struct net_device *ndev) 92 { 93 return AX88796C_REGDUMP_LEN + AX88796C_PHY_REGDUMP_LEN; 94 } 95 96 static void 97 ax88796c_get_regs(struct net_device *ndev, struct ethtool_regs *regs, void *_p) 98 { 99 struct ax88796c_device *ax_local = to_ax88796c_device(ndev); 100 int offset, i; 101 u16 *p = _p; 102 103 memset(p, 0, ax88796c_get_regs_len(ndev)); 104 105 mutex_lock(&ax_local->spi_lock); 106 107 for (offset = 0; offset < AX88796C_REGDUMP_LEN; offset += 2) { 108 if (!test_bit(offset / 2, ax88796c_no_regs_mask)) 109 *p = AX_READ(&ax_local->ax_spi, offset); 110 p++; 111 } 112 113 mutex_unlock(&ax_local->spi_lock); 114 115 for (i = 0; i < AX88796C_PHY_REGDUMP_LEN / 2; i++) { 116 *p = phy_read(ax_local->phydev, i); 117 p++; 118 } 119 } 120 121 static void 122 ax88796c_get_strings(struct net_device *ndev, u32 stringset, u8 *data) 123 { 124 switch (stringset) { 125 case ETH_SS_PRIV_FLAGS: 126 memcpy(data, ax88796c_priv_flag_names, 127 sizeof(ax88796c_priv_flag_names)); 128 break; 129 } 130 } 131 132 static int 133 ax88796c_get_sset_count(struct net_device *ndev, int stringset) 134 { 135 int ret = 0; 136 137 switch (stringset) { 138 case ETH_SS_PRIV_FLAGS: 139 ret = ARRAY_SIZE(ax88796c_priv_flag_names); 140 break; 141 default: 142 ret = -EOPNOTSUPP; 143 } 144 145 return ret; 146 } 147 148 static int ax88796c_set_priv_flags(struct net_device *ndev, u32 flags) 149 { 150 struct ax88796c_device *ax_local = to_ax88796c_device(ndev); 151 152 if (flags & ~AX_PRIV_FLAGS_MASK) 153 return -EOPNOTSUPP; 154 155 if ((ax_local->priv_flags ^ flags) & AX_CAP_COMP) 156 if (netif_running(ndev)) 157 return -EBUSY; 158 159 ax_local->priv_flags = flags; 160 161 return 0; 162 } 163 164 static u32 ax88796c_get_priv_flags(struct net_device *ndev) 165 { 166 struct ax88796c_device *ax_local = to_ax88796c_device(ndev); 167 168 return ax_local->priv_flags; 169 } 170 171 int ax88796c_mdio_read(struct mii_bus *mdiobus, int phy_id, int loc) 172 { 173 struct ax88796c_device *ax_local = mdiobus->priv; 174 int ret; 175 176 mutex_lock(&ax_local->spi_lock); 177 AX_WRITE(&ax_local->ax_spi, MDIOCR_RADDR(loc) 178 | MDIOCR_FADDR(phy_id) | MDIOCR_READ, P2_MDIOCR); 179 180 ret = read_poll_timeout(AX_READ, ret, 181 (ret != 0), 182 0, jiffies_to_usecs(HZ / 100), false, 183 &ax_local->ax_spi, P2_MDIOCR); 184 if (!ret) 185 ret = AX_READ(&ax_local->ax_spi, P2_MDIODR); 186 187 mutex_unlock(&ax_local->spi_lock); 188 189 return ret; 190 } 191 192 int 193 ax88796c_mdio_write(struct mii_bus *mdiobus, int phy_id, int loc, u16 val) 194 { 195 struct ax88796c_device *ax_local = mdiobus->priv; 196 int ret; 197 198 mutex_lock(&ax_local->spi_lock); 199 AX_WRITE(&ax_local->ax_spi, val, P2_MDIODR); 200 201 AX_WRITE(&ax_local->ax_spi, 202 MDIOCR_RADDR(loc) | MDIOCR_FADDR(phy_id) 203 | MDIOCR_WRITE, P2_MDIOCR); 204 205 ret = read_poll_timeout(AX_READ, ret, 206 ((ret & MDIOCR_VALID) != 0), 0, 207 jiffies_to_usecs(HZ / 100), false, 208 &ax_local->ax_spi, P2_MDIOCR); 209 mutex_unlock(&ax_local->spi_lock); 210 211 return ret; 212 } 213 214 const struct ethtool_ops ax88796c_ethtool_ops = { 215 .get_drvinfo = ax88796c_get_drvinfo, 216 .get_link = ethtool_op_get_link, 217 .get_msglevel = ax88796c_get_msglevel, 218 .set_msglevel = ax88796c_set_msglevel, 219 .get_link_ksettings = phy_ethtool_get_link_ksettings, 220 .set_link_ksettings = phy_ethtool_set_link_ksettings, 221 .nway_reset = phy_ethtool_nway_reset, 222 .get_pauseparam = ax88796c_get_pauseparam, 223 .set_pauseparam = ax88796c_set_pauseparam, 224 .get_regs_len = ax88796c_get_regs_len, 225 .get_regs = ax88796c_get_regs, 226 .get_strings = ax88796c_get_strings, 227 .get_sset_count = ax88796c_get_sset_count, 228 .get_priv_flags = ax88796c_get_priv_flags, 229 .set_priv_flags = ax88796c_set_priv_flags, 230 }; 231 232 int ax88796c_ioctl(struct net_device *ndev, struct ifreq *ifr, int cmd) 233 { 234 int ret; 235 236 ret = phy_mii_ioctl(ndev->phydev, ifr, cmd); 237 238 return ret; 239 } 240