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

cicada.c (3636B)


      1// SPDX-License-Identifier: GPL-2.0+
      2/*
      3 * drivers/net/phy/cicada.c
      4 *
      5 * Driver for Cicada PHYs
      6 *
      7 * Author: Andy Fleming
      8 *
      9 * Copyright (c) 2004 Freescale Semiconductor, Inc.
     10 */
     11#include <linux/kernel.h>
     12#include <linux/string.h>
     13#include <linux/errno.h>
     14#include <linux/unistd.h>
     15#include <linux/interrupt.h>
     16#include <linux/init.h>
     17#include <linux/delay.h>
     18#include <linux/netdevice.h>
     19#include <linux/etherdevice.h>
     20#include <linux/skbuff.h>
     21#include <linux/spinlock.h>
     22#include <linux/mm.h>
     23#include <linux/module.h>
     24#include <linux/mii.h>
     25#include <linux/ethtool.h>
     26#include <linux/phy.h>
     27
     28#include <linux/io.h>
     29#include <asm/irq.h>
     30#include <linux/uaccess.h>
     31
     32/* Cicada Extended Control Register 1 */
     33#define MII_CIS8201_EXT_CON1           0x17
     34#define MII_CIS8201_EXTCON1_INIT       0x0000
     35
     36/* Cicada Interrupt Mask Register */
     37#define MII_CIS8201_IMASK		0x19
     38#define MII_CIS8201_IMASK_IEN		0x8000
     39#define MII_CIS8201_IMASK_SPEED	0x4000
     40#define MII_CIS8201_IMASK_LINK		0x2000
     41#define MII_CIS8201_IMASK_DUPLEX	0x1000
     42#define MII_CIS8201_IMASK_MASK		0xf000
     43
     44/* Cicada Interrupt Status Register */
     45#define MII_CIS8201_ISTAT		0x1a
     46#define MII_CIS8201_ISTAT_STATUS	0x8000
     47#define MII_CIS8201_ISTAT_SPEED	0x4000
     48#define MII_CIS8201_ISTAT_LINK		0x2000
     49#define MII_CIS8201_ISTAT_DUPLEX	0x1000
     50
     51/* Cicada Auxiliary Control/Status Register */
     52#define MII_CIS8201_AUX_CONSTAT        0x1c
     53#define MII_CIS8201_AUXCONSTAT_INIT    0x0004
     54#define MII_CIS8201_AUXCONSTAT_DUPLEX  0x0020
     55#define MII_CIS8201_AUXCONSTAT_SPEED   0x0018
     56#define MII_CIS8201_AUXCONSTAT_GBIT    0x0010
     57#define MII_CIS8201_AUXCONSTAT_100     0x0008
     58
     59MODULE_DESCRIPTION("Cicadia PHY driver");
     60MODULE_AUTHOR("Andy Fleming");
     61MODULE_LICENSE("GPL");
     62
     63static int cis820x_config_init(struct phy_device *phydev)
     64{
     65	int err;
     66
     67	err = phy_write(phydev, MII_CIS8201_AUX_CONSTAT,
     68			MII_CIS8201_AUXCONSTAT_INIT);
     69
     70	if (err < 0)
     71		return err;
     72
     73	err = phy_write(phydev, MII_CIS8201_EXT_CON1,
     74			MII_CIS8201_EXTCON1_INIT);
     75
     76	return err;
     77}
     78
     79static int cis820x_ack_interrupt(struct phy_device *phydev)
     80{
     81	int err = phy_read(phydev, MII_CIS8201_ISTAT);
     82
     83	return (err < 0) ? err : 0;
     84}
     85
     86static int cis820x_config_intr(struct phy_device *phydev)
     87{
     88	int err;
     89
     90	if (phydev->interrupts == PHY_INTERRUPT_ENABLED) {
     91		err = cis820x_ack_interrupt(phydev);
     92		if (err)
     93			return err;
     94
     95		err = phy_write(phydev, MII_CIS8201_IMASK,
     96				MII_CIS8201_IMASK_MASK);
     97	} else {
     98		err = phy_write(phydev, MII_CIS8201_IMASK, 0);
     99		if (err)
    100			return err;
    101
    102		err = cis820x_ack_interrupt(phydev);
    103	}
    104
    105	return err;
    106}
    107
    108static irqreturn_t cis820x_handle_interrupt(struct phy_device *phydev)
    109{
    110	int irq_status;
    111
    112	irq_status = phy_read(phydev, MII_CIS8201_ISTAT);
    113	if (irq_status < 0) {
    114		phy_error(phydev);
    115		return IRQ_NONE;
    116	}
    117
    118	if (!(irq_status & MII_CIS8201_IMASK_MASK))
    119		return IRQ_NONE;
    120
    121	phy_trigger_machine(phydev);
    122
    123	return IRQ_HANDLED;
    124}
    125
    126/* Cicada 8201, a.k.a Vitesse VSC8201 */
    127static struct phy_driver cis820x_driver[] = {
    128{
    129	.phy_id		= 0x000fc410,
    130	.name		= "Cicada Cis8201",
    131	.phy_id_mask	= 0x000ffff0,
    132	/* PHY_GBIT_FEATURES */
    133	.config_init	= &cis820x_config_init,
    134	.config_intr	= &cis820x_config_intr,
    135	.handle_interrupt = &cis820x_handle_interrupt,
    136}, {
    137	.phy_id		= 0x000fc440,
    138	.name		= "Cicada Cis8204",
    139	.phy_id_mask	= 0x000fffc0,
    140	/* PHY_GBIT_FEATURES */
    141	.config_init	= &cis820x_config_init,
    142	.config_intr	= &cis820x_config_intr,
    143	.handle_interrupt = &cis820x_handle_interrupt,
    144} };
    145
    146module_phy_driver(cis820x_driver);
    147
    148static struct mdio_device_id __maybe_unused cicada_tbl[] = {
    149	{ 0x000fc410, 0x000ffff0 },
    150	{ 0x000fc440, 0x000fffc0 },
    151	{ }
    152};
    153
    154MODULE_DEVICE_TABLE(mdio, cicada_tbl);