1// SPDX-License-Identifier: GPL-2.0+ 2/* 3 * drivers/net/phy/lxt.c 4 * 5 * Driver for Intel LXT PHYs 6 * 7 * Author: Andy Fleming 8 * 9 * Copyright (c) 2004 Freescale Semiconductor, Inc. 10 */ 11#include <linux/kernel.h> 12#include <linux/string.h> 13#include <linux/errno.h> 14#include <linux/unistd.h> 15#include <linux/interrupt.h> 16#include <linux/init.h> 17#include <linux/delay.h> 18#include <linux/netdevice.h> 19#include <linux/etherdevice.h> 20#include <linux/skbuff.h> 21#include <linux/spinlock.h> 22#include <linux/mm.h> 23#include <linux/module.h> 24#include <linux/mii.h> 25#include <linux/ethtool.h> 26#include <linux/phy.h> 27 28#include <asm/io.h> 29#include <asm/irq.h> 30#include <linux/uaccess.h> 31 32/* The Level one LXT970 is used by many boards */ 33 34#define MII_LXT970_IER 17 /* Interrupt Enable Register */ 35 36#define MII_LXT970_IER_IEN 0x0002 37 38#define MII_LXT970_ISR 18 /* Interrupt Status Register */ 39 40#define MII_LXT970_CONFIG 19 /* Configuration Register */ 41 42/* ------------------------------------------------------------------------- */ 43/* The Level one LXT971 is used on some of my custom boards */ 44 45/* register definitions for the 971 */ 46#define MII_LXT971_IER 18 /* Interrupt Enable Register */ 47#define MII_LXT971_IER_IEN 0x00f2 48 49#define MII_LXT971_ISR 19 /* Interrupt Status Register */ 50 51/* register definitions for the 973 */ 52#define MII_LXT973_PCR 16 /* Port Configuration Register */ 53#define PCR_FIBER_SELECT 1 54 55MODULE_DESCRIPTION("Intel LXT PHY driver"); 56MODULE_AUTHOR("Andy Fleming"); 57MODULE_LICENSE("GPL"); 58 59static int lxt970_ack_interrupt(struct phy_device *phydev) 60{ 61 int err; 62 63 err = phy_read(phydev, MII_BMSR); 64 65 if (err < 0) 66 return err; 67 68 err = phy_read(phydev, MII_LXT970_ISR); 69 70 if (err < 0) 71 return err; 72 73 return 0; 74} 75 76static int lxt970_config_intr(struct phy_device *phydev) 77{ 78 if (phydev->interrupts == PHY_INTERRUPT_ENABLED) 79 return phy_write(phydev, MII_LXT970_IER, MII_LXT970_IER_IEN); 80 else 81 return phy_write(phydev, MII_LXT970_IER, 0); 82} 83 84static int lxt970_config_init(struct phy_device *phydev) 85{ 86 return phy_write(phydev, MII_LXT970_CONFIG, 0); 87} 88 89 90static int lxt971_ack_interrupt(struct phy_device *phydev) 91{ 92 int err = phy_read(phydev, MII_LXT971_ISR); 93 94 if (err < 0) 95 return err; 96 97 return 0; 98} 99 100static int lxt971_config_intr(struct phy_device *phydev) 101{ 102 if (phydev->interrupts == PHY_INTERRUPT_ENABLED) 103 return phy_write(phydev, MII_LXT971_IER, MII_LXT971_IER_IEN); 104 else 105 return phy_write(phydev, MII_LXT971_IER, 0); 106} 107 108/* 109 * A2 version of LXT973 chip has an ERRATA: it randomly return the contents 110 * of the previous even register when you read a odd register regularly 111 */ 112 113static int lxt973a2_update_link(struct phy_device *phydev) 114{ 115 int status; 116 int control; 117 int retry = 8; /* we try 8 times */ 118 119 /* Do a fake read */ 120 status = phy_read(phydev, MII_BMSR); 121 122 if (status < 0) 123 return status; 124 125 control = phy_read(phydev, MII_BMCR); 126 if (control < 0) 127 return control; 128 129 do { 130 /* Read link and autonegotiation status */ 131 status = phy_read(phydev, MII_BMSR); 132 } while (status >= 0 && retry-- && status == control); 133 134 if (status < 0) 135 return status; 136 137 if ((status & BMSR_LSTATUS) == 0) 138 phydev->link = 0; 139 else 140 phydev->link = 1; 141 142 return 0; 143} 144 145static int lxt973a2_read_status(struct phy_device *phydev) 146{ 147 int adv; 148 int err; 149 int lpa; 150 151 /* Update the link, but return if there was an error */ 152 err = lxt973a2_update_link(phydev); 153 if (err) 154 return err; 155 156 if (AUTONEG_ENABLE == phydev->autoneg) { 157 int retry = 1; 158 159 adv = phy_read(phydev, MII_ADVERTISE); 160 161 if (adv < 0) 162 return adv; 163 164 do { 165 lpa = phy_read(phydev, MII_LPA); 166 167 if (lpa < 0) 168 return lpa; 169 170 /* If both registers are equal, it is suspect but not 171 * impossible, hence a new try 172 */ 173 } while (lpa == adv && retry--); 174 175 mii_lpa_to_linkmode_lpa_t(phydev->lp_advertising, lpa); 176 177 lpa &= adv; 178 179 phydev->speed = SPEED_10; 180 phydev->duplex = DUPLEX_HALF; 181 phydev->pause = phydev->asym_pause = 0; 182 183 if (lpa & (LPA_100FULL | LPA_100HALF)) { 184 phydev->speed = SPEED_100; 185 186 if (lpa & LPA_100FULL) 187 phydev->duplex = DUPLEX_FULL; 188 } else { 189 if (lpa & LPA_10FULL) 190 phydev->duplex = DUPLEX_FULL; 191 } 192 193 phy_resolve_aneg_pause(phydev); 194 } else { 195 err = genphy_read_status_fixed(phydev); 196 if (err < 0) 197 return err; 198 199 phydev->pause = phydev->asym_pause = 0; 200 linkmode_zero(phydev->lp_advertising); 201 } 202 203 return 0; 204} 205 206static int lxt973_probe(struct phy_device *phydev) 207{ 208 int val = phy_read(phydev, MII_LXT973_PCR); 209 210 if (val & PCR_FIBER_SELECT) { 211 /* 212 * If fiber is selected, then the only correct setting 213 * is 100Mbps, full duplex, and auto negotiation off. 214 */ 215 val = phy_read(phydev, MII_BMCR); 216 val |= (BMCR_SPEED100 | BMCR_FULLDPLX); 217 val &= ~BMCR_ANENABLE; 218 phy_write(phydev, MII_BMCR, val); 219 /* Remember that the port is in fiber mode. */ 220 phydev->priv = lxt973_probe; 221 phydev->port = PORT_FIBRE; 222 } else { 223 phydev->priv = NULL; 224 } 225 return 0; 226} 227 228static int lxt973_config_aneg(struct phy_device *phydev) 229{ 230 /* Do nothing if port is in fiber mode. */ 231 return phydev->priv ? 0 : genphy_config_aneg(phydev); 232} 233 234static struct phy_driver lxt97x_driver[] = { 235{ 236 .phy_id = 0x78100000, 237 .name = "LXT970", 238 .phy_id_mask = 0xfffffff0, 239 /* PHY_BASIC_FEATURES */ 240 .config_init = lxt970_config_init, 241 .ack_interrupt = lxt970_ack_interrupt, 242 .config_intr = lxt970_config_intr, 243}, { 244 .phy_id = 0x001378e0, 245 .name = "LXT971", 246 .phy_id_mask = 0xfffffff0, 247 /* PHY_BASIC_FEATURES */ 248 .ack_interrupt = lxt971_ack_interrupt, 249 .config_intr = lxt971_config_intr, 250 .suspend = genphy_suspend, 251 .resume = genphy_resume, 252}, { 253 .phy_id = 0x00137a10, 254 .name = "LXT973-A2", 255 .phy_id_mask = 0xffffffff, 256 /* PHY_BASIC_FEATURES */ 257 .flags = 0, 258 .probe = lxt973_probe, 259 .config_aneg = lxt973_config_aneg, 260 .read_status = lxt973a2_read_status, 261 .suspend = genphy_suspend, 262 .resume = genphy_resume, 263}, { 264 .phy_id = 0x00137a10, 265 .name = "LXT973", 266 .phy_id_mask = 0xfffffff0, 267 /* PHY_BASIC_FEATURES */ 268 .flags = 0, 269 .probe = lxt973_probe, 270 .config_aneg = lxt973_config_aneg, 271 .suspend = genphy_suspend, 272 .resume = genphy_resume, 273} }; 274 275module_phy_driver(lxt97x_driver); 276 277static struct mdio_device_id __maybe_unused lxt_tbl[] = { 278 { 0x78100000, 0xfffffff0 }, 279 { 0x001378e0, 0xfffffff0 }, 280 { 0x00137a10, 0xfffffff0 }, 281 { } 282}; 283 284MODULE_DEVICE_TABLE(mdio, lxt_tbl); 285