cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

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);