cregit-Linux how code gets into the kernel

Release 4.11 drivers/net/phy/vitesse.c

Directory: drivers/net/phy
/*
 * Driver for Vitesse PHYs
 *
 * Author: Kriston Carson
 *
 * Copyright (c) 2005, 2009, 2011 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/module.h>
#include <linux/mii.h>
#include <linux/ethtool.h>
#include <linux/phy.h>

/* Vitesse Extended Page Magic Register(s) */

#define MII_VSC82X4_EXT_PAGE_16E	0x10

#define MII_VSC82X4_EXT_PAGE_17E	0x11

#define MII_VSC82X4_EXT_PAGE_18E	0x12

/* Vitesse Extended Control Register 1 */

#define MII_VSC8244_EXT_CON1           0x17

#define MII_VSC8244_EXTCON1_INIT       0x0000

#define MII_VSC8244_EXTCON1_TX_SKEW_MASK	0x0c00

#define MII_VSC8244_EXTCON1_RX_SKEW_MASK	0x0300

#define MII_VSC8244_EXTCON1_TX_SKEW	0x0800

#define MII_VSC8244_EXTCON1_RX_SKEW	0x0200

/* Vitesse Interrupt Mask Register */

#define MII_VSC8244_IMASK		0x19

#define MII_VSC8244_IMASK_IEN		0x8000

#define MII_VSC8244_IMASK_SPEED		0x4000

#define MII_VSC8244_IMASK_LINK		0x2000

#define MII_VSC8244_IMASK_DUPLEX	0x1000

#define MII_VSC8244_IMASK_MASK		0xf000


#define MII_VSC8221_IMASK_MASK		0xa000

/* Vitesse Interrupt Status Register */

#define MII_VSC8244_ISTAT		0x1a

#define MII_VSC8244_ISTAT_STATUS	0x8000

#define MII_VSC8244_ISTAT_SPEED		0x4000

#define MII_VSC8244_ISTAT_LINK		0x2000

#define MII_VSC8244_ISTAT_DUPLEX	0x1000

/* Vitesse Auxiliary Control/Status Register */

#define MII_VSC8244_AUX_CONSTAT		0x1c

#define MII_VSC8244_AUXCONSTAT_INIT	0x0000

#define MII_VSC8244_AUXCONSTAT_DUPLEX	0x0020

#define MII_VSC8244_AUXCONSTAT_SPEED	0x0018

#define MII_VSC8244_AUXCONSTAT_GBIT	0x0010

#define MII_VSC8244_AUXCONSTAT_100	0x0008


#define MII_VSC8221_AUXCONSTAT_INIT	0x0004 
/* need to set this bit? */

#define MII_VSC8221_AUXCONSTAT_RESERVED	0x0004

/* Vitesse Extended Page Access Register */

#define MII_VSC82X4_EXT_PAGE_ACCESS	0x1f

/* Vitesse VSC8601 Extended PHY Control Register 1 */

#define MII_VSC8601_EPHY_CTL		0x17

#define MII_VSC8601_EPHY_CTL_RGMII_SKEW	(1 << 8)


#define PHY_ID_VSC8234			0x000fc620

#define PHY_ID_VSC8244			0x000fc6c0

#define PHY_ID_VSC8514			0x00070670

#define PHY_ID_VSC8572			0x000704d0

#define PHY_ID_VSC8574			0x000704a0

#define PHY_ID_VSC8601			0x00070420

#define PHY_ID_VSC8662			0x00070660

#define PHY_ID_VSC8221			0x000fc550

#define PHY_ID_VSC8211			0x000fc4b0

MODULE_DESCRIPTION("Vitesse PHY driver");
MODULE_AUTHOR("Kriston Carson");
MODULE_LICENSE("GPL");


static int vsc824x_add_skew(struct phy_device *phydev) { int err; int extcon; extcon = phy_read(phydev, MII_VSC8244_EXT_CON1); if (extcon < 0) return extcon; extcon &= ~(MII_VSC8244_EXTCON1_TX_SKEW_MASK | MII_VSC8244_EXTCON1_RX_SKEW_MASK); extcon |= (MII_VSC8244_EXTCON1_TX_SKEW | MII_VSC8244_EXTCON1_RX_SKEW); err = phy_write(phydev, MII_VSC8244_EXT_CON1, extcon); return err; }

Contributors

PersonTokensPropCommitsCommitProp
Andy Fleming4162.12%250.00%
Jon Loeliger2436.36%125.00%
Stephen Hemminger11.52%125.00%
Total66100.00%4100.00%


static int vsc824x_config_init(struct phy_device *phydev) { int err; err = phy_write(phydev, MII_VSC8244_AUX_CONSTAT, MII_VSC8244_AUXCONSTAT_INIT); if (err < 0) return err; if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID) err = vsc824x_add_skew(phydev); return err; }

Contributors

PersonTokensPropCommitsCommitProp
Andy Fleming52100.00%1100.00%
Total52100.00%1100.00%

/* This adds a skew for both TX and RX clocks, so the skew should only be * applied to "rgmii-id" interfaces. It may not work as expected * on "rgmii-txid", "rgmii-rxid" or "rgmii" interfaces. */
static int vsc8601_add_skew(struct phy_device *phydev) { int ret; ret = phy_read(phydev, MII_VSC8601_EPHY_CTL); if (ret < 0) return ret; ret |= MII_VSC8601_EPHY_CTL_RGMII_SKEW; return phy_write(phydev, MII_VSC8601_EPHY_CTL, ret); }

Contributors

PersonTokensPropCommitsCommitProp
Alex Gershgorin46100.00%1100.00%
Total46100.00%1100.00%


static int vsc8601_config_init(struct phy_device *phydev) { int ret = 0; if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID) ret = vsc8601_add_skew(phydev); if (ret < 0) return ret; return genphy_config_init(phydev); }

Contributors

PersonTokensPropCommitsCommitProp
Alex Gershgorin46100.00%1100.00%
Total46100.00%1100.00%


static int vsc824x_ack_interrupt(struct phy_device *phydev) { int err = 0; /* Don't bother to ACK the interrupts if interrupts * are disabled. The 824x cannot clear the interrupts * if they are disabled. */ if (phydev->interrupts == PHY_INTERRUPT_ENABLED) err = phy_read(phydev, MII_VSC8244_ISTAT); return (err < 0) ? err : 0; }

Contributors

PersonTokensPropCommitsCommitProp
Jon Loeliger3168.89%133.33%
Andy Fleming1328.89%133.33%
Michal Simek12.22%133.33%
Total45100.00%3100.00%


static int vsc82xx_config_intr(struct phy_device *phydev) { int err; if (phydev->interrupts == PHY_INTERRUPT_ENABLED) err = phy_write(phydev, MII_VSC8244_IMASK, (phydev->drv->phy_id == PHY_ID_VSC8234 || phydev->drv->phy_id == PHY_ID_VSC8244 || phydev->drv->phy_id == PHY_ID_VSC8514 || phydev->drv->phy_id == PHY_ID_VSC8572 || phydev->drv->phy_id == PHY_ID_VSC8574 || phydev->drv->phy_id == PHY_ID_VSC8601) ? MII_VSC8244_IMASK_MASK : MII_VSC8221_IMASK_MASK); else { /* The Vitesse PHY cannot clear the interrupt * once it has disabled them, so we clear them first */ err = phy_read(phydev, MII_VSC8244_ISTAT); if (err < 0) return err; err = phy_write(phydev, MII_VSC8244_IMASK, 0); } return err; }

Contributors

PersonTokensPropCommitsCommitProp
Jon Loeliger4738.84%110.00%
Andy Fleming3024.79%330.00%
Shaohui Xie1613.22%220.00%
Trent Piepho119.09%110.00%
Måns Rullgård86.61%110.00%
Stephen Agate86.61%110.00%
Michal Simek10.83%110.00%
Total121100.00%10100.00%


static int vsc8221_config_init(struct phy_device *phydev) { int err; err = phy_write(phydev, MII_VSC8244_AUX_CONSTAT, MII_VSC8221_AUXCONSTAT_INIT); return err; /* Perhaps we should set EXT_CON1 based on the interface? * Options are 802.3Z SerDes or SGMII */ }

Contributors

PersonTokensPropCommitsCommitProp
Christian Hohnstaedt2896.55%150.00%
Michal Simek13.45%150.00%
Total29100.00%2100.00%

/* vsc82x4_config_autocross_enable - Enable auto MDI/MDI-X for forced links * @phydev: target phy_device struct * * Enable auto MDI/MDI-X when in 10/100 forced link speeds by writing * special values in the VSC8234/VSC8244 extended reserved registers */
static int vsc82x4_config_autocross_enable(struct phy_device *phydev) { int ret; if (phydev->autoneg == AUTONEG_ENABLE || phydev->speed > SPEED_100) return 0; /* map extended registers set 0x10 - 0x1e */ ret = phy_write(phydev, MII_VSC82X4_EXT_PAGE_ACCESS, 0x52b5); if (ret >= 0) ret = phy_write(phydev, MII_VSC82X4_EXT_PAGE_18E, 0x0012); if (ret >= 0) ret = phy_write(phydev, MII_VSC82X4_EXT_PAGE_17E, 0x2803); if (ret >= 0) ret = phy_write(phydev, MII_VSC82X4_EXT_PAGE_16E, 0x87fa); /* map standard registers set 0x10 - 0x1e */ if (ret >= 0) ret = phy_write(phydev, MII_VSC82X4_EXT_PAGE_ACCESS, 0x0000); else phy_write(phydev, MII_VSC82X4_EXT_PAGE_ACCESS, 0x0000); return ret; }

Contributors

PersonTokensPropCommitsCommitProp
Madalin Bucur125100.00%1100.00%
Total125100.00%1100.00%

/* vsc82x4_config_aneg - restart auto-negotiation or write BMCR * @phydev: target phy_device struct * * Description: If auto-negotiation is enabled, we configure the * advertising, and then restart auto-negotiation. If it is not * enabled, then we write the BMCR and also start the auto * MDI/MDI-X feature */
static int vsc82x4_config_aneg(struct phy_device *phydev) { int ret; /* Enable auto MDI/MDI-X when in 10/100 forced link speeds by * writing special values in the VSC8234 extended reserved registers */ if (phydev->autoneg != AUTONEG_ENABLE && phydev->speed <= SPEED_100) { ret = genphy_setup_forced(phydev); if (ret < 0) /* error */ return ret; return vsc82x4_config_autocross_enable(phydev); } return genphy_config_aneg(phydev); }

Contributors

PersonTokensPropCommitsCommitProp
Madalin Bucur60100.00%1100.00%
Total60100.00%1100.00%

/* Vitesse 82xx */ static struct phy_driver vsc82xx_driver[] = { { .phy_id = PHY_ID_VSC8234, .name = "Vitesse VSC8234", .phy_id_mask = 0x000ffff0, .features = PHY_GBIT_FEATURES, .flags = PHY_HAS_INTERRUPT, .config_init = &vsc824x_config_init, .config_aneg = &vsc82x4_config_aneg, .read_status = &genphy_read_status, .ack_interrupt = &vsc824x_ack_interrupt, .config_intr = &vsc82xx_config_intr, }, { .phy_id = PHY_ID_VSC8244, .name = "Vitesse VSC8244", .phy_id_mask = 0x000fffc0, .features = PHY_GBIT_FEATURES, .flags = PHY_HAS_INTERRUPT, .config_init = &vsc824x_config_init, .config_aneg = &vsc82x4_config_aneg, .read_status = &genphy_read_status, .ack_interrupt = &vsc824x_ack_interrupt, .config_intr = &vsc82xx_config_intr, }, { .phy_id = PHY_ID_VSC8514, .name = "Vitesse VSC8514", .phy_id_mask = 0x000ffff0, .features = PHY_GBIT_FEATURES, .flags = PHY_HAS_INTERRUPT, .config_init = &vsc824x_config_init, .config_aneg = &vsc82x4_config_aneg, .read_status = &genphy_read_status, .ack_interrupt = &vsc824x_ack_interrupt, .config_intr = &vsc82xx_config_intr, }, { .phy_id = PHY_ID_VSC8572, .name = "Vitesse VSC8572", .phy_id_mask = 0x000ffff0, .features = PHY_GBIT_FEATURES, .flags = PHY_HAS_INTERRUPT, .config_init = &vsc824x_config_init, .config_aneg = &vsc82x4_config_aneg, .read_status = &genphy_read_status, .ack_interrupt = &vsc824x_ack_interrupt, .config_intr = &vsc82xx_config_intr, }, { .phy_id = PHY_ID_VSC8574, .name = "Vitesse VSC8574", .phy_id_mask = 0x000ffff0, .features = PHY_GBIT_FEATURES, .flags = PHY_HAS_INTERRUPT, .config_init = &vsc824x_config_init, .config_aneg = &vsc82x4_config_aneg, .read_status = &genphy_read_status, .ack_interrupt = &vsc824x_ack_interrupt, .config_intr = &vsc82xx_config_intr, }, { .phy_id = PHY_ID_VSC8601, .name = "Vitesse VSC8601", .phy_id_mask = 0x000ffff0, .features = PHY_GBIT_FEATURES, .flags = PHY_HAS_INTERRUPT, .config_init = &vsc8601_config_init, .config_aneg = &genphy_config_aneg, .read_status = &genphy_read_status, .ack_interrupt = &vsc824x_ack_interrupt, .config_intr = &vsc82xx_config_intr, }, { .phy_id = PHY_ID_VSC8662, .name = "Vitesse VSC8662", .phy_id_mask = 0x000ffff0, .features = PHY_GBIT_FEATURES, .flags = PHY_HAS_INTERRUPT, .config_init = &vsc824x_config_init, .config_aneg = &vsc82x4_config_aneg, .read_status = &genphy_read_status, .ack_interrupt = &vsc824x_ack_interrupt, .config_intr = &vsc82xx_config_intr, }, { /* Vitesse 8221 */ .phy_id = PHY_ID_VSC8221, .phy_id_mask = 0x000ffff0, .name = "Vitesse VSC8221", .features = PHY_GBIT_FEATURES, .flags = PHY_HAS_INTERRUPT, .config_init = &vsc8221_config_init, .config_aneg = &genphy_config_aneg, .read_status = &genphy_read_status, .ack_interrupt = &vsc824x_ack_interrupt, .config_intr = &vsc82xx_config_intr, }, { /* Vitesse 8211 */ .phy_id = PHY_ID_VSC8211, .phy_id_mask = 0x000ffff0, .name = "Vitesse VSC8211", .features = PHY_GBIT_FEATURES, .flags = PHY_HAS_INTERRUPT, .config_init = &vsc8221_config_init, .config_aneg = &genphy_config_aneg, .read_status = &genphy_read_status, .ack_interrupt = &vsc824x_ack_interrupt, .config_intr = &vsc82xx_config_intr, } }; module_phy_driver(vsc82xx_driver); static struct mdio_device_id __maybe_unused vitesse_tbl[] = { { PHY_ID_VSC8234, 0x000ffff0 }, { PHY_ID_VSC8244, 0x000fffc0 }, { PHY_ID_VSC8514, 0x000ffff0 }, { PHY_ID_VSC8572, 0x000ffff0 }, { PHY_ID_VSC8574, 0x000ffff0 }, { PHY_ID_VSC8662, 0x000ffff0 }, { PHY_ID_VSC8221, 0x000ffff0 }, { PHY_ID_VSC8211, 0x000ffff0 }, { } }; MODULE_DEVICE_TABLE(mdio, vitesse_tbl);

Overall Contributors

PersonTokensPropCommitsCommitProp
Jon Loeliger27119.48%14.76%
Andy Fleming22015.82%523.81%
Madalin Bucur21015.10%14.76%
Shaohui Xie14910.71%29.52%
Alex Gershgorin1037.40%14.76%
Trent Piepho926.61%14.76%
Stephen Agate755.39%14.76%
Michal Simek715.10%29.52%
Måns Rullgård684.89%14.76%
Sandeep Singh664.74%14.76%
Christian Hohnstaedt332.37%14.76%
David Woodhouse292.08%14.76%
Johan Hovold20.14%14.76%
Stephen Hemminger10.07%14.76%
Uwe Kleine-König10.07%14.76%
Total1391100.00%21100.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.