18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0+ 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Driver for AMD am79c PHYs 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Author: Heiko Schocher <hs@denx.de> 68c2ecf20Sopenharmony_ci * 78c2ecf20Sopenharmony_ci * Copyright (c) 2011 DENX Software Engineering GmbH 88c2ecf20Sopenharmony_ci */ 98c2ecf20Sopenharmony_ci#include <linux/kernel.h> 108c2ecf20Sopenharmony_ci#include <linux/errno.h> 118c2ecf20Sopenharmony_ci#include <linux/init.h> 128c2ecf20Sopenharmony_ci#include <linux/module.h> 138c2ecf20Sopenharmony_ci#include <linux/mii.h> 148c2ecf20Sopenharmony_ci#include <linux/phy.h> 158c2ecf20Sopenharmony_ci 168c2ecf20Sopenharmony_ci#define PHY_ID_AM79C874 0x0022561b 178c2ecf20Sopenharmony_ci 188c2ecf20Sopenharmony_ci#define MII_AM79C_IR 17 /* Interrupt Status/Control Register */ 198c2ecf20Sopenharmony_ci#define MII_AM79C_IR_EN_LINK 0x0400 /* IR enable Linkstate */ 208c2ecf20Sopenharmony_ci#define MII_AM79C_IR_EN_ANEG 0x0100 /* IR enable Aneg Complete */ 218c2ecf20Sopenharmony_ci#define MII_AM79C_IR_IMASK_INIT (MII_AM79C_IR_EN_LINK | MII_AM79C_IR_EN_ANEG) 228c2ecf20Sopenharmony_ci 238c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("AMD PHY driver"); 248c2ecf20Sopenharmony_ciMODULE_AUTHOR("Heiko Schocher <hs@denx.de>"); 258c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL"); 268c2ecf20Sopenharmony_ci 278c2ecf20Sopenharmony_cistatic int am79c_ack_interrupt(struct phy_device *phydev) 288c2ecf20Sopenharmony_ci{ 298c2ecf20Sopenharmony_ci int err; 308c2ecf20Sopenharmony_ci 318c2ecf20Sopenharmony_ci err = phy_read(phydev, MII_BMSR); 328c2ecf20Sopenharmony_ci if (err < 0) 338c2ecf20Sopenharmony_ci return err; 348c2ecf20Sopenharmony_ci 358c2ecf20Sopenharmony_ci err = phy_read(phydev, MII_AM79C_IR); 368c2ecf20Sopenharmony_ci if (err < 0) 378c2ecf20Sopenharmony_ci return err; 388c2ecf20Sopenharmony_ci 398c2ecf20Sopenharmony_ci return 0; 408c2ecf20Sopenharmony_ci} 418c2ecf20Sopenharmony_ci 428c2ecf20Sopenharmony_cistatic int am79c_config_init(struct phy_device *phydev) 438c2ecf20Sopenharmony_ci{ 448c2ecf20Sopenharmony_ci return 0; 458c2ecf20Sopenharmony_ci} 468c2ecf20Sopenharmony_ci 478c2ecf20Sopenharmony_cistatic int am79c_config_intr(struct phy_device *phydev) 488c2ecf20Sopenharmony_ci{ 498c2ecf20Sopenharmony_ci int err; 508c2ecf20Sopenharmony_ci 518c2ecf20Sopenharmony_ci if (phydev->interrupts == PHY_INTERRUPT_ENABLED) 528c2ecf20Sopenharmony_ci err = phy_write(phydev, MII_AM79C_IR, MII_AM79C_IR_IMASK_INIT); 538c2ecf20Sopenharmony_ci else 548c2ecf20Sopenharmony_ci err = phy_write(phydev, MII_AM79C_IR, 0); 558c2ecf20Sopenharmony_ci 568c2ecf20Sopenharmony_ci return err; 578c2ecf20Sopenharmony_ci} 588c2ecf20Sopenharmony_ci 598c2ecf20Sopenharmony_cistatic struct phy_driver am79c_driver[] = { { 608c2ecf20Sopenharmony_ci .phy_id = PHY_ID_AM79C874, 618c2ecf20Sopenharmony_ci .name = "AM79C874", 628c2ecf20Sopenharmony_ci .phy_id_mask = 0xfffffff0, 638c2ecf20Sopenharmony_ci /* PHY_BASIC_FEATURES */ 648c2ecf20Sopenharmony_ci .config_init = am79c_config_init, 658c2ecf20Sopenharmony_ci .ack_interrupt = am79c_ack_interrupt, 668c2ecf20Sopenharmony_ci .config_intr = am79c_config_intr, 678c2ecf20Sopenharmony_ci} }; 688c2ecf20Sopenharmony_ci 698c2ecf20Sopenharmony_cimodule_phy_driver(am79c_driver); 708c2ecf20Sopenharmony_ci 718c2ecf20Sopenharmony_cistatic struct mdio_device_id __maybe_unused amd_tbl[] = { 728c2ecf20Sopenharmony_ci { PHY_ID_AM79C874, 0xfffffff0 }, 738c2ecf20Sopenharmony_ci { } 748c2ecf20Sopenharmony_ci}; 758c2ecf20Sopenharmony_ci 768c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(mdio, amd_tbl); 77