1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * Driver for AMD am79c PHYs 4 * 5 * Author: Heiko Schocher <hs@denx.de> 6 * 7 * Copyright (c) 2011 DENX Software Engineering GmbH 8 */ 9 #include <linux/kernel.h> 10 #include <linux/errno.h> 11 #include <linux/init.h> 12 #include <linux/module.h> 13 #include <linux/mii.h> 14 #include <linux/phy.h> 15 16 #define PHY_ID_AM79C874 0x0022561b 17 18 #define MII_AM79C_IR 17 /* Interrupt Status/Control Register */ 19 #define MII_AM79C_IR_EN_LINK 0x0400 /* IR enable Linkstate */ 20 #define MII_AM79C_IR_EN_ANEG 0x0100 /* IR enable Aneg Complete */ 21 #define MII_AM79C_IR_IMASK_INIT (MII_AM79C_IR_EN_LINK | MII_AM79C_IR_EN_ANEG) 22 23 MODULE_DESCRIPTION("AMD PHY driver"); 24 MODULE_AUTHOR("Heiko Schocher <hs@denx.de>"); 25 MODULE_LICENSE("GPL"); 26 27 static int am79c_ack_interrupt(struct phy_device *phydev) 28 { 29 int err; 30 31 err = phy_read(phydev, MII_BMSR); 32 if (err < 0) 33 return err; 34 35 err = phy_read(phydev, MII_AM79C_IR); 36 if (err < 0) 37 return err; 38 39 return 0; 40 } 41 42 static int am79c_config_init(struct phy_device *phydev) 43 { 44 return 0; 45 } 46 47 static int am79c_config_intr(struct phy_device *phydev) 48 { 49 int err; 50 51 if (phydev->interrupts == PHY_INTERRUPT_ENABLED) 52 err = phy_write(phydev, MII_AM79C_IR, MII_AM79C_IR_IMASK_INIT); 53 else 54 err = phy_write(phydev, MII_AM79C_IR, 0); 55 56 return err; 57 } 58 59 static struct phy_driver am79c_driver[] = { { 60 .phy_id = PHY_ID_AM79C874, 61 .name = "AM79C874", 62 .phy_id_mask = 0xfffffff0, 63 /* PHY_BASIC_FEATURES */ 64 .config_init = am79c_config_init, 65 .ack_interrupt = am79c_ack_interrupt, 66 .config_intr = am79c_config_intr, 67 } }; 68 69 module_phy_driver(am79c_driver); 70 71 static struct mdio_device_id __maybe_unused amd_tbl[] = { 72 { PHY_ID_AM79C874, 0xfffffff0 }, 73 { } 74 }; 75 76 MODULE_DEVICE_TABLE(mdio, amd_tbl); 77