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 23MODULE_DESCRIPTION("AMD PHY driver"); 24MODULE_AUTHOR("Heiko Schocher <hs@denx.de>"); 25MODULE_LICENSE("GPL"); 26 27static 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 42static int am79c_config_init(struct phy_device *phydev) 43{ 44 return 0; 45} 46 47static 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 59static 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 69module_phy_driver(am79c_driver); 70 71static struct mdio_device_id __maybe_unused amd_tbl[] = { 72 { PHY_ID_AM79C874, 0xfffffff0 }, 73 { } 74}; 75 76MODULE_DEVICE_TABLE(mdio, amd_tbl); 77