brintos

brintos / linux-shallow public Read only

0
0
Text · 2.6 KiB · 930b15f Raw
121 lines · c
1// SPDX-License-Identifier: GPL-2.0+2/*3 * Driver for AMD am79c PHYs4 *5 * Author: Heiko Schocher <hs@denx.de>6 *7 * Copyright (c) 2011 DENX Software Engineering GmbH8 */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_AC101L		0x0022552017#define PHY_ID_AM79C874		0x0022561b18 19#define MII_AM79C_IR		17	/* Interrupt Status/Control Register */20#define MII_AM79C_IR_EN_LINK	0x0400	/* IR enable Linkstate */21#define MII_AM79C_IR_EN_ANEG	0x0100	/* IR enable Aneg Complete */22#define MII_AM79C_IR_IMASK_INIT	(MII_AM79C_IR_EN_LINK | MII_AM79C_IR_EN_ANEG)23 24#define MII_AM79C_IR_LINK_DOWN	BIT(2)25#define MII_AM79C_IR_ANEG_DONE	BIT(0)26#define MII_AM79C_IR_IMASK_STAT	(MII_AM79C_IR_LINK_DOWN | MII_AM79C_IR_ANEG_DONE)27 28MODULE_DESCRIPTION("AMD PHY driver");29MODULE_AUTHOR("Heiko Schocher <hs@denx.de>");30MODULE_LICENSE("GPL");31 32static 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 47static int am79c_config_init(struct phy_device *phydev)48{49	return 0;50}51 52static int am79c_config_intr(struct phy_device *phydev)53{54	int err;55 56	if (phydev->interrupts == PHY_INTERRUPT_ENABLED) {57		err = am79c_ack_interrupt(phydev);58		if (err)59			return err;60 61		err = phy_write(phydev, MII_AM79C_IR, MII_AM79C_IR_IMASK_INIT);62	} else {63		err = phy_write(phydev, MII_AM79C_IR, 0);64		if (err)65			return err;66 67		err = am79c_ack_interrupt(phydev);68	}69 70	return err;71}72 73static irqreturn_t am79c_handle_interrupt(struct phy_device *phydev)74{75	int irq_status;76 77	irq_status = phy_read(phydev, MII_AM79C_IR);78	if (irq_status < 0) {79		phy_error(phydev);80		return IRQ_NONE;81	}82 83	if (!(irq_status & MII_AM79C_IR_IMASK_STAT))84		return IRQ_NONE;85 86	phy_trigger_machine(phydev);87 88	return IRQ_HANDLED;89}90 91static struct phy_driver am79c_drivers[] = {92	{93		.phy_id		= PHY_ID_AM79C874,94		.name		= "AM79C874",95		.phy_id_mask	= 0xfffffff0,96		/* PHY_BASIC_FEATURES */97		.config_init	= am79c_config_init,98		.config_intr	= am79c_config_intr,99		.handle_interrupt = am79c_handle_interrupt,100	},101	{102		.phy_id		= PHY_ID_AC101L,103		.name		= "AC101L",104		.phy_id_mask	= 0xfffffff0,105		/* PHY_BASIC_FEATURES */106		.config_init	= am79c_config_init,107		.config_intr	= am79c_config_intr,108		.handle_interrupt = am79c_handle_interrupt,109	},110};111 112module_phy_driver(am79c_drivers);113 114static struct mdio_device_id __maybe_unused amd_tbl[] = {115	{ PHY_ID_AC101L, 0xfffffff0 },116	{ PHY_ID_AM79C874, 0xfffffff0 },117	{ }118};119 120MODULE_DEVICE_TABLE(mdio, amd_tbl);121