1 /* 2 * Driver for AMD am79c PHYs 3 * 4 * Author: Heiko Schocher <hs@denx.de> 5 * 6 * Copyright (c) 2011 DENX Software Engineering GmbH 7 * 8 * This program is free software; you can redistribute it and/or modify it 9 * under the terms of the GNU General Public License as published by the 10 * Free Software Foundation; either version 2 of the License, or (at your 11 * option) any later version. 12 * 13 */ 14 #include <linux/kernel.h> 15 #include <linux/errno.h> 16 #include <linux/init.h> 17 #include <linux/module.h> 18 #include <linux/mii.h> 19 #include <linux/phy.h> 20 21 #define PHY_ID_AM79C874 0x0022561b 22 23 #define MII_AM79C_IR 17 /* Interrupt Status/Control Register */ 24 #define MII_AM79C_IR_EN_LINK 0x0400 /* IR enable Linkstate */ 25 #define MII_AM79C_IR_EN_ANEG 0x0100 /* IR enable Aneg Complete */ 26 #define MII_AM79C_IR_IMASK_INIT (MII_AM79C_IR_EN_LINK | MII_AM79C_IR_EN_ANEG) 27 28 MODULE_DESCRIPTION("AMD PHY driver"); 29 MODULE_AUTHOR("Heiko Schocher <hs@denx.de>"); 30 MODULE_LICENSE("GPL"); 31 32 static int am79c_ack_interrupt(struct phy_device *phydev) 33 { 34 int err; 35 36 err = phy_read(phydev, MII_BMSR); 37 if (err < 0) 38 return err; 39 40 err = phy_read(phydev, MII_AM79C_IR); 41 if (err < 0) 42 return err; 43 44 return 0; 45 } 46 47 static int am79c_config_init(struct phy_device *phydev) 48 { 49 return 0; 50 } 51 52 static int am79c_config_intr(struct phy_device *phydev) 53 { 54 int err; 55 56 if (phydev->interrupts == PHY_INTERRUPT_ENABLED) 57 err = phy_write(phydev, MII_AM79C_IR, MII_AM79C_IR_IMASK_INIT); 58 else 59 err = phy_write(phydev, MII_AM79C_IR, 0); 60 61 return err; 62 } 63 64 static struct phy_driver am79c_driver = { 65 .phy_id = PHY_ID_AM79C874, 66 .name = "AM79C874", 67 .phy_id_mask = 0xfffffff0, 68 .features = PHY_BASIC_FEATURES, 69 .flags = PHY_HAS_INTERRUPT, 70 .config_init = am79c_config_init, 71 .config_aneg = genphy_config_aneg, 72 .read_status = genphy_read_status, 73 .ack_interrupt = am79c_ack_interrupt, 74 .config_intr = am79c_config_intr, 75 .driver = { .owner = THIS_MODULE,}, 76 }; 77 78 static int __init am79c_init(void) 79 { 80 int ret; 81 82 ret = phy_driver_register(&am79c_driver); 83 if (ret) 84 return ret; 85 86 return 0; 87 } 88 89 static void __exit am79c_exit(void) 90 { 91 phy_driver_unregister(&am79c_driver); 92 } 93 94 module_init(am79c_init); 95 module_exit(am79c_exit); 96 97 static struct mdio_device_id __maybe_unused amd_tbl[] = { 98 { PHY_ID_AM79C874, 0xfffffff0 }, 99 { } 100 }; 101 102 MODULE_DEVICE_TABLE(mdio, amd_tbl); 103