cregit-Linux how code gets into the kernel

Release 4.16 drivers/net/phy/smsc.c

Directory: drivers/net/phy
/*
 * drivers/net/phy/smsc.c
 *
 * Driver for SMSC PHYs
 *
 * Author: Herbert Valerio Riedel
 *
 * Copyright (c) 2006 Herbert Valerio Riedel <hvr@gnu.org>
 *
 * 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.
 *
 * Support added for SMSC LAN8187 and LAN8700 by steve.glendinning@shawell.net
 *
 */

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/mii.h>
#include <linux/ethtool.h>
#include <linux/of.h>
#include <linux/phy.h>
#include <linux/netdevice.h>
#include <linux/smscphy.h>


struct smsc_hw_stat {
	
const char *string;
	
u8 reg;
	
u8 bits;
};


static struct smsc_hw_stat smsc_hw_stats[] = {
	{ "phy_symbol_errors", 26, 16},
};


struct smsc_phy_priv {
	
bool energy_enable;
};


static int smsc_phy_config_intr(struct phy_device *phydev) { int rc = phy_write (phydev, MII_LAN83C185_IM, ((PHY_INTERRUPT_ENABLED == phydev->interrupts) ? MII_LAN83C185_ISF_INT_PHYLIB_EVENTS : 0)); return rc < 0 ? rc : 0; }

Contributors

PersonTokensPropCommitsCommitProp
Herbert Valerio Riedel4397.73%150.00%
Steve Glendinning12.27%150.00%
Total44100.00%2100.00%


static int smsc_phy_ack_interrupt(struct phy_device *phydev) { int rc = phy_read (phydev, MII_LAN83C185_ISF); return rc < 0 ? rc : 0; }

Contributors

PersonTokensPropCommitsCommitProp
Herbert Valerio Riedel2996.67%150.00%
Steve Glendinning13.33%150.00%
Total30100.00%2100.00%


static int smsc_phy_config_init(struct phy_device *phydev) { struct smsc_phy_priv *priv = phydev->priv; int rc = phy_read(phydev, MII_LAN83C185_CTRL_STATUS); if (rc < 0) return rc; if (priv->energy_enable) { /* Enable energy detect mode for this SMSC Transceivers */ rc = phy_write(phydev, MII_LAN83C185_CTRL_STATUS, rc | MII_LAN83C185_EDPWRDOWN); if (rc < 0) return rc; } return smsc_phy_ack_interrupt(phydev); }

Contributors

PersonTokensPropCommitsCommitProp
Gwenhael Goavec-Merou4255.26%116.67%
Heiko Schocher1215.79%116.67%
Herbert Valerio Riedel911.84%116.67%
Giuseppe Cavallaro67.89%116.67%
Teresa Remmet67.89%116.67%
Steve Glendinning11.32%116.67%
Total76100.00%6100.00%


static int smsc_phy_reset(struct phy_device *phydev) { int rc = phy_read(phydev, MII_LAN83C185_SPECIAL_MODES); if (rc < 0) return rc; /* If the SMSC PHY is in power down mode, then set it * in all capable mode before using it. */ if ((rc & MII_LAN83C185_MODE_MASK) == MII_LAN83C185_MODE_POWERDOWN) { /* set "all capable" mode */ rc |= MII_LAN83C185_MODE_ALL; phy_write(phydev, MII_LAN83C185_SPECIAL_MODES, rc); } /* reset the phy */ return genphy_soft_reset(phydev); }

Contributors

PersonTokensPropCommitsCommitProp
Philippe Reynes3046.88%125.00%
Gwenhael Goavec-Merou1726.56%125.00%
Giuseppe Cavallaro1320.31%125.00%
Manfred Schlaegl46.25%125.00%
Total64100.00%4100.00%


static int lan911x_config_init(struct phy_device *phydev) { return smsc_phy_ack_interrupt(phydev); }

Contributors

PersonTokensPropCommitsCommitProp
Patrick Trantham17100.00%1100.00%
Total17100.00%1100.00%

/* * The LAN87xx suffers from rare absence of the ENERGYON-bit when Ethernet cable * plugs in while LAN87xx is in Energy Detect Power-Down mode. This leads to * unstable detection of plugging in Ethernet cable. * This workaround disables Energy Detect Power-Down mode and waiting for * response on link pulses to detect presence of plugged Ethernet cable. * The Energy Detect Power-Down mode is enabled again in the end of procedure to * save approximately 220 mW of power if cable is unplugged. */
static int lan87xx_read_status(struct phy_device *phydev) { struct smsc_phy_priv *priv = phydev->priv; int err = genphy_read_status(phydev); if (!phydev->link && priv->energy_enable) { int i; /* Disable EDPD to wake up PHY */ int rc = phy_read(phydev, MII_LAN83C185_CTRL_STATUS); if (rc < 0) return rc; rc = phy_write(phydev, MII_LAN83C185_CTRL_STATUS, rc & ~MII_LAN83C185_EDPWRDOWN); if (rc < 0) return rc; /* Wait max 640 ms to detect energy */ for (i = 0; i < 64; i++) { /* Sleep to allow link test pulses to be sent */ msleep(10); rc = phy_read(phydev, MII_LAN83C185_CTRL_STATUS); if (rc < 0) return rc; if (rc & MII_LAN83C185_ENERGYON) break; } /* Re-enable EDPD */ rc = phy_read(phydev, MII_LAN83C185_CTRL_STATUS); if (rc < 0) return rc; rc = phy_write(phydev, MII_LAN83C185_CTRL_STATUS, rc | MII_LAN83C185_EDPWRDOWN); if (rc < 0) return rc; } return err; }

Contributors

PersonTokensPropCommitsCommitProp
Patrick Trantham6234.83%116.67%
Marek Vašut5028.09%116.67%
Igor Plyatov4324.16%116.67%
Teresa Remmet168.99%116.67%
Herbert Valerio Riedel63.37%116.67%
Giuseppe Cavallaro10.56%116.67%
Total178100.00%6100.00%


static int smsc_get_sset_count(struct phy_device *phydev) { return ARRAY_SIZE(smsc_hw_stats); }

Contributors

PersonTokensPropCommitsCommitProp
Andrew Lunn17100.00%1100.00%
Total17100.00%1100.00%


static void smsc_get_strings(struct phy_device *phydev, u8 *data) { int i; for (i = 0; i < ARRAY_SIZE(smsc_hw_stats); i++) { strncpy(data + i * ETH_GSTRING_LEN, smsc_hw_stats[i].string, ETH_GSTRING_LEN); } }

Contributors

PersonTokensPropCommitsCommitProp
Andrew Lunn5398.15%150.00%
Arnd Bergmann11.85%150.00%
Total54100.00%2100.00%

#ifndef UINT64_MAX #define UINT64_MAX (u64)(~((u64)0)) #endif
static u64 smsc_get_stat(struct phy_device *phydev, int i) { struct smsc_hw_stat stat = smsc_hw_stats[i]; int val; u64 ret; val = phy_read(phydev, stat.reg); if (val < 0) ret = UINT64_MAX; else ret = val; return ret; }

Contributors

PersonTokensPropCommitsCommitProp
Andrew Lunn58100.00%1100.00%
Total58100.00%1100.00%


static void smsc_get_stats(struct phy_device *phydev, struct ethtool_stats *stats, u64 *data) { int i; for (i = 0; i < ARRAY_SIZE(smsc_hw_stats); i++) data[i] = smsc_get_stat(phydev, i); }

Contributors

PersonTokensPropCommitsCommitProp
Andrew Lunn51100.00%1100.00%
Total51100.00%1100.00%


static int smsc_phy_probe(struct phy_device *phydev) { struct device *dev = &phydev->mdio.dev; struct device_node *of_node = dev->of_node; struct smsc_phy_priv *priv; priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); if (!priv) return -ENOMEM; priv->energy_enable = true; if (of_property_read_bool(of_node, "smsc,disable-energy-detect")) priv->energy_enable = false; phydev->priv = priv; return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Teresa Remmet91100.00%1100.00%
Total91100.00%1100.00%

static struct phy_driver smsc_phy_driver[] = { { .phy_id = 0x0007c0a0, /* OUI=0x00800f, Model#=0x0a */ .phy_id_mask = 0xfffffff0, .name = "SMSC LAN83C185", .features = PHY_BASIC_FEATURES, .flags = PHY_HAS_INTERRUPT, .probe = smsc_phy_probe, /* basic functions */ .config_init = smsc_phy_config_init, .soft_reset = smsc_phy_reset, /* IRQ related */ .ack_interrupt = smsc_phy_ack_interrupt, .config_intr = smsc_phy_config_intr, .suspend = genphy_suspend, .resume = genphy_resume, }, { .phy_id = 0x0007c0b0, /* OUI=0x00800f, Model#=0x0b */ .phy_id_mask = 0xfffffff0, .name = "SMSC LAN8187", .features = PHY_BASIC_FEATURES, .flags = PHY_HAS_INTERRUPT, .probe = smsc_phy_probe, /* basic functions */ .config_init = smsc_phy_config_init, .soft_reset = smsc_phy_reset, /* IRQ related */ .ack_interrupt = smsc_phy_ack_interrupt, .config_intr = smsc_phy_config_intr, /* Statistics */ .get_sset_count = smsc_get_sset_count, .get_strings = smsc_get_strings, .get_stats = smsc_get_stats, .suspend = genphy_suspend, .resume = genphy_resume, }, { .phy_id = 0x0007c0c0, /* OUI=0x00800f, Model#=0x0c */ .phy_id_mask = 0xfffffff0, .name = "SMSC LAN8700", .features = PHY_BASIC_FEATURES, .flags = PHY_HAS_INTERRUPT, .probe = smsc_phy_probe, /* basic functions */ .read_status = lan87xx_read_status, .config_init = smsc_phy_config_init, .soft_reset = smsc_phy_reset, /* IRQ related */ .ack_interrupt = smsc_phy_ack_interrupt, .config_intr = smsc_phy_config_intr, /* Statistics */ .get_sset_count = smsc_get_sset_count, .get_strings = smsc_get_strings, .get_stats = smsc_get_stats, .suspend = genphy_suspend, .resume = genphy_resume, }, { .phy_id = 0x0007c0d0, /* OUI=0x00800f, Model#=0x0d */ .phy_id_mask = 0xfffffff0, .name = "SMSC LAN911x Internal PHY", .features = PHY_BASIC_FEATURES, .flags = PHY_HAS_INTERRUPT, .probe = smsc_phy_probe, /* basic functions */ .config_init = lan911x_config_init, /* IRQ related */ .ack_interrupt = smsc_phy_ack_interrupt, .config_intr = smsc_phy_config_intr, .suspend = genphy_suspend, .resume = genphy_resume, }, { .phy_id = 0x0007c0f0, /* OUI=0x00800f, Model#=0x0f */ .phy_id_mask = 0xfffffff0, .name = "SMSC LAN8710/LAN8720", .features = PHY_BASIC_FEATURES, .flags = PHY_HAS_INTERRUPT | PHY_RST_AFTER_CLK_EN, .probe = smsc_phy_probe, /* basic functions */ .read_status = lan87xx_read_status, .config_init = smsc_phy_config_init, .soft_reset = smsc_phy_reset, /* IRQ related */ .ack_interrupt = smsc_phy_ack_interrupt, .config_intr = smsc_phy_config_intr, /* Statistics */ .get_sset_count = smsc_get_sset_count, .get_strings = smsc_get_strings, .get_stats = smsc_get_stats, .suspend = genphy_suspend, .resume = genphy_resume, }, { .phy_id = 0x0007c110, .phy_id_mask = 0xfffffff0, .name = "SMSC LAN8740", .features = PHY_BASIC_FEATURES, .flags = PHY_HAS_INTERRUPT, .probe = smsc_phy_probe, /* basic functions */ .read_status = lan87xx_read_status, .config_init = smsc_phy_config_init, .soft_reset = smsc_phy_reset, /* IRQ related */ .ack_interrupt = smsc_phy_ack_interrupt, .config_intr = smsc_phy_config_intr, /* Statistics */ .get_sset_count = smsc_get_sset_count, .get_strings = smsc_get_strings, .get_stats = smsc_get_stats, .suspend = genphy_suspend, .resume = genphy_resume, } }; module_phy_driver(smsc_phy_driver); MODULE_DESCRIPTION("SMSC PHY driver"); MODULE_AUTHOR("Herbert Valerio Riedel"); MODULE_LICENSE("GPL"); static struct mdio_device_id __maybe_unused smsc_tbl[] = { { 0x0007c0a0, 0xfffffff0 }, { 0x0007c0b0, 0xfffffff0 }, { 0x0007c0c0, 0xfffffff0 }, { 0x0007c0d0, 0xfffffff0 }, { 0x0007c0f0, 0xfffffff0 }, { 0x0007c110, 0xfffffff0 }, { } }; MODULE_DEVICE_TABLE(mdio, smsc_tbl);

Overall Contributors

PersonTokensPropCommitsCommitProp
Andrew Lunn28722.04%27.14%
Steve Glendinning24018.43%621.43%
Herbert Valerio Riedel16712.83%13.57%
Teresa Remmet15111.60%13.57%
Patrick Trantham826.30%27.14%
Gwenhael Goavec-Merou796.07%13.57%
Joshua Henderson705.38%13.57%
Marek Vašut503.84%13.57%
David Woodhouse473.61%13.57%
Igor Plyatov453.46%13.57%
Philippe Reynes302.30%13.57%
Giuseppe Cavallaro211.61%13.57%
Heiko Schocher120.92%13.57%
Christian Hohnstaedt80.61%13.57%
Manfred Schlaegl40.31%13.57%
Javier Martinez Canillas30.23%13.57%
Richard Leitner20.15%13.57%
Shruti Kanetkar10.08%13.57%
Uwe Kleine-König10.08%13.57%
Arnd Bergmann10.08%13.57%
Johan Hovold10.08%13.57%
Total1302100.00%28100.00%
Directory: drivers/net/phy
Information contained on this website is for historical information purposes only and does not indicate or represent copyright ownership.
Created with cregit.