amd.c (2339B)
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#define MII_AM79C_IR_LINK_DOWN BIT(2) 24#define MII_AM79C_IR_ANEG_DONE BIT(0) 25#define MII_AM79C_IR_IMASK_STAT (MII_AM79C_IR_LINK_DOWN | MII_AM79C_IR_ANEG_DONE) 26 27MODULE_DESCRIPTION("AMD PHY driver"); 28MODULE_AUTHOR("Heiko Schocher <hs@denx.de>"); 29MODULE_LICENSE("GPL"); 30 31static int am79c_ack_interrupt(struct phy_device *phydev) 32{ 33 int err; 34 35 err = phy_read(phydev, MII_BMSR); 36 if (err < 0) 37 return err; 38 39 err = phy_read(phydev, MII_AM79C_IR); 40 if (err < 0) 41 return err; 42 43 return 0; 44} 45 46static int am79c_config_init(struct phy_device *phydev) 47{ 48 return 0; 49} 50 51static int am79c_config_intr(struct phy_device *phydev) 52{ 53 int err; 54 55 if (phydev->interrupts == PHY_INTERRUPT_ENABLED) { 56 err = am79c_ack_interrupt(phydev); 57 if (err) 58 return err; 59 60 err = phy_write(phydev, MII_AM79C_IR, MII_AM79C_IR_IMASK_INIT); 61 } else { 62 err = phy_write(phydev, MII_AM79C_IR, 0); 63 if (err) 64 return err; 65 66 err = am79c_ack_interrupt(phydev); 67 } 68 69 return err; 70} 71 72static irqreturn_t am79c_handle_interrupt(struct phy_device *phydev) 73{ 74 int irq_status; 75 76 irq_status = phy_read(phydev, MII_AM79C_IR); 77 if (irq_status < 0) { 78 phy_error(phydev); 79 return IRQ_NONE; 80 } 81 82 if (!(irq_status & MII_AM79C_IR_IMASK_STAT)) 83 return IRQ_NONE; 84 85 phy_trigger_machine(phydev); 86 87 return IRQ_HANDLED; 88} 89 90static struct phy_driver am79c_driver[] = { { 91 .phy_id = PHY_ID_AM79C874, 92 .name = "AM79C874", 93 .phy_id_mask = 0xfffffff0, 94 /* PHY_BASIC_FEATURES */ 95 .config_init = am79c_config_init, 96 .config_intr = am79c_config_intr, 97 .handle_interrupt = am79c_handle_interrupt, 98} }; 99 100module_phy_driver(am79c_driver); 101 102static struct mdio_device_id __maybe_unused amd_tbl[] = { 103 { PHY_ID_AM79C874, 0xfffffff0 }, 104 { } 105}; 106 107MODULE_DEVICE_TABLE(mdio, amd_tbl);