cregit-Linux how code gets into the kernel

Release 4.7 drivers/net/phy/lxt.c

Directory: drivers/net/phy
/*
 * drivers/net/phy/lxt.c
 *
 * Driver for Intel LXT PHYs
 *
 * Author: Andy Fleming
 *
 * Copyright (c) 2004 Freescale Semiconductor, Inc.
 *
 * This program is free software; you can redistribute  it and/or modify it
 * under  the terms of  the GNU General  Public License as published by the
 * Free Software Foundation;  either version 2 of the  License, or (at your
 * option) any later version.
 *
 */
#include <linux/kernel.h>
#include <linux/string.h>
#include <linux/errno.h>
#include <linux/unistd.h>
#include <linux/interrupt.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/skbuff.h>
#include <linux/spinlock.h>
#include <linux/mm.h>
#include <linux/module.h>
#include <linux/mii.h>
#include <linux/ethtool.h>
#include <linux/phy.h>

#include <asm/io.h>
#include <asm/irq.h>
#include <asm/uaccess.h>

/* The Level one LXT970 is used by many boards                               */


#define MII_LXT970_IER       17  
/* Interrupt Enable Register */


#define MII_LXT970_IER_IEN	0x0002


#define MII_LXT970_ISR       18  
/* Interrupt Status Register */


#define MII_LXT970_CONFIG    19  
/* Configuration Register    */

/* ------------------------------------------------------------------------- */
/* The Level one LXT971 is used on some of my custom boards                  */

/* register definitions for the 971 */

#define MII_LXT971_IER		18  
/* Interrupt Enable Register */

#define MII_LXT971_IER_IEN	0x00f2


#define MII_LXT971_ISR		19  
/* Interrupt Status Register */

/* register definitions for the 973 */

#define MII_LXT973_PCR 16 
/* Port Configuration Register */

#define PCR_FIBER_SELECT 1

MODULE_DESCRIPTION("Intel LXT PHY driver");
MODULE_AUTHOR("Andy Fleming");
MODULE_LICENSE("GPL");


static int lxt970_ack_interrupt(struct phy_device *phydev) { int err; err = phy_read(phydev, MII_BMSR); if (err < 0) return err; err = phy_read(phydev, MII_LXT970_ISR); if (err < 0) return err; return 0; }

Contributors

PersonTokensPropCommitsCommitProp
andy flemingandy fleming53100.00%1100.00%
Total53100.00%1100.00%


static int lxt970_config_intr(struct phy_device *phydev) { if (phydev->interrupts == PHY_INTERRUPT_ENABLED) return phy_write(phydev, MII_LXT970_IER, MII_LXT970_IER_IEN); else return phy_write(phydev, MII_LXT970_IER, 0); }

Contributors

PersonTokensPropCommitsCommitProp
andy flemingandy fleming3792.50%150.00%
sergei shtylyovsergei shtylyov37.50%150.00%
Total40100.00%2100.00%


static int lxt970_config_init(struct phy_device *phydev) { return phy_write(phydev, MII_LXT970_CONFIG, 0); }

Contributors

PersonTokensPropCommitsCommitProp
andy flemingandy fleming2095.24%150.00%
sergei shtylyovsergei shtylyov14.76%150.00%
Total21100.00%2100.00%


static int lxt971_ack_interrupt(struct phy_device *phydev) { int err = phy_read(phydev, MII_LXT971_ISR); if (err < 0) return err; return 0; }

Contributors

PersonTokensPropCommitsCommitProp
andy flemingandy fleming33100.00%1100.00%
Total33100.00%1100.00%


static int lxt971_config_intr(struct phy_device *phydev) { if (phydev->interrupts == PHY_INTERRUPT_ENABLED) return phy_write(phydev, MII_LXT971_IER, MII_LXT971_IER_IEN); else return phy_write(phydev, MII_LXT971_IER, 0); }

Contributors

PersonTokensPropCommitsCommitProp
andy flemingandy fleming3792.50%150.00%
sergei shtylyovsergei shtylyov37.50%150.00%
Total40100.00%2100.00%

/* * A2 version of LXT973 chip has an ERRATA: it randomly return the contents * of the previous even register when you read a odd register regularly */
static int lxt973a2_update_link(struct phy_device *phydev) { int status; int control; int retry = 8; /* we try 8 times */ /* Do a fake read */ status = phy_read(phydev, MII_BMSR); if (status < 0) return status; control = phy_read(phydev, MII_BMCR); if (control < 0) return control; do { /* Read link and autonegotiation status */ status = phy_read(phydev, MII_BMSR); } while (status >= 0 && retry-- && status == control); if (status < 0) return status; if ((status & BMSR_LSTATUS) == 0) phydev->link = 0; else phydev->link = 1; return 0; }

Contributors

PersonTokensPropCommitsCommitProp
christophe leroychristophe leroy122100.00%1100.00%
Total122100.00%1100.00%


static int lxt973a2_read_status(struct phy_device *phydev) { int adv; int err; int lpa; int lpagb = 0; /* Update the link, but return if there was an error */ err = lxt973a2_update_link(phydev); if (err) return err; if (AUTONEG_ENABLE == phydev->autoneg) { int retry = 1; adv = phy_read(phydev, MII_ADVERTISE); if (adv < 0) return adv; do { lpa = phy_read(phydev, MII_LPA); if (lpa < 0) return lpa; /* If both registers are equal, it is suspect but not * impossible, hence a new try */ } while (lpa == adv && retry--); lpa &= adv; phydev->speed = SPEED_10; phydev->duplex = DUPLEX_HALF; phydev->pause = phydev->asym_pause = 0; if (lpagb & (LPA_1000FULL | LPA_1000HALF)) { phydev->speed = SPEED_1000; if (lpagb & LPA_1000FULL) phydev->duplex = DUPLEX_FULL; } else if (lpa & (LPA_100FULL | LPA_100HALF)) { phydev->speed = SPEED_100; if (lpa & LPA_100FULL) phydev->duplex = DUPLEX_FULL; } else { if (lpa & LPA_10FULL) phydev->duplex = DUPLEX_FULL; } if (phydev->duplex == DUPLEX_FULL) { phydev->pause = lpa & LPA_PAUSE_CAP ? 1 : 0; phydev->asym_pause = lpa & LPA_PAUSE_ASYM ? 1 : 0; } } else { int bmcr = phy_read(phydev, MII_BMCR); if (bmcr < 0) return bmcr; if (bmcr & BMCR_FULLDPLX) phydev->duplex = DUPLEX_FULL; else phydev->duplex = DUPLEX_HALF; if (bmcr & BMCR_SPEED1000) phydev->speed = SPEED_1000; else if (bmcr & BMCR_SPEED100) phydev->speed = SPEED_100; else phydev->speed = SPEED_10; phydev->pause = phydev->asym_pause = 0; } return 0; }

Contributors

PersonTokensPropCommitsCommitProp
christophe leroychristophe leroy32699.69%150.00%
stephen hemmingerstephen hemminger10.31%150.00%
Total327100.00%2100.00%


static int lxt973_probe(struct phy_device *phydev) { int val = phy_read(phydev, MII_LXT973_PCR); if (val & PCR_FIBER_SELECT) { /* * If fiber is selected, then the only correct setting * is 100Mbps, full duplex, and auto negotiation off. */ val = phy_read(phydev, MII_BMCR); val |= (BMCR_SPEED100 | BMCR_FULLDPLX); val &= ~BMCR_ANENABLE; phy_write(phydev, MII_BMCR, val); /* Remember that the port is in fiber mode. */ phydev->priv = lxt973_probe; } else { phydev->priv = NULL; } return 0; }

Contributors

PersonTokensPropCommitsCommitProp
richard cochranrichard cochran80100.00%1100.00%
Total80100.00%1100.00%


static int lxt973_config_aneg(struct phy_device *phydev) { /* Do nothing if port is in fiber mode. */ return phydev->priv ? 0 : genphy_config_aneg(phydev); }

Contributors

PersonTokensPropCommitsCommitProp
richard cochranrichard cochran24100.00%1100.00%
Total24100.00%1100.00%

static struct phy_driver lxt97x_driver[] = { { .phy_id = 0x78100000, .name = "LXT970", .phy_id_mask = 0xfffffff0, .features = PHY_BASIC_FEATURES, .flags = PHY_HAS_INTERRUPT, .config_init = lxt970_config_init, .config_aneg = genphy_config_aneg, .read_status = genphy_read_status, .ack_interrupt = lxt970_ack_interrupt, .config_intr = lxt970_config_intr, }, { .phy_id = 0x001378e0, .name = "LXT971", .phy_id_mask = 0xfffffff0, .features = PHY_BASIC_FEATURES, .flags = PHY_HAS_INTERRUPT, .config_aneg = genphy_config_aneg, .read_status = genphy_read_status, .ack_interrupt = lxt971_ack_interrupt, .config_intr = lxt971_config_intr, }, { .phy_id = 0x00137a10, .name = "LXT973-A2", .phy_id_mask = 0xffffffff, .features = PHY_BASIC_FEATURES, .flags = 0, .probe = lxt973_probe, .config_aneg = lxt973_config_aneg, .read_status = lxt973a2_read_status, }, { .phy_id = 0x00137a10, .name = "LXT973", .phy_id_mask = 0xfffffff0, .features = PHY_BASIC_FEATURES, .flags = 0, .probe = lxt973_probe, .config_aneg = lxt973_config_aneg, .read_status = genphy_read_status, } }; module_phy_driver(lxt97x_driver); static struct mdio_device_id __maybe_unused lxt_tbl[] = { { 0x78100000, 0xfffffff0 }, { 0x001378e0, 0xfffffff0 }, { 0x00137a10, 0xfffffff0 }, { } }; MODULE_DEVICE_TABLE(mdio, lxt_tbl);

Overall Contributors

PersonTokensPropCommitsCommitProp
christophe leroychristophe leroy49144.92%18.33%
andy flemingandy fleming39035.68%18.33%
richard cochranrichard cochran15614.27%18.33%
david woodhousedavid woodhouse353.20%216.67%
sergei shtylyovsergei shtylyov70.64%216.67%
christian hohnstaedtchristian hohnstaedt60.55%18.33%
uwe zeisbergeruwe zeisberger40.37%18.33%
johan hovoldjohan hovold20.18%18.33%
stephen hemmingerstephen hemminger10.09%18.33%
uwe kleine-koeniguwe kleine-koenig10.09%18.33%
Total1093100.00%12100.00%
Directory: drivers/net/phy
Information contained on this website is for historical information purposes only and does not indicate or represent copyright ownership.
{% endraw %}