mirror of https://gitee.com/openkylin/linux.git
Microsemi VSC 8531/41 PHY Driver
Hello, I added all review comments and re-sending for review. >From a5017f5878a92d2acec86a6a29b1498c457cb73a Mon Sep 17 00:00:00 2001 From: Nagaraju Lakkaraju <Raju.Lakkaraju@microsemi.com> Date: Wed, 3 Aug 2016 18:28:24 +0530 Subject: [PATCH v2] net: phy: Add drivers for Microsemi PHYs Signed-off-by: Nagaraju Lakkaraju <Raju.Lakkaraju@microsemi.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
07bf2e11ad
commit
d50736a853
|
@ -307,6 +307,11 @@ config MDIO_XGENE
|
|||
This module provides a driver for the MDIO busses found in the
|
||||
APM X-Gene SoC's.
|
||||
|
||||
config MICROSEMI_PHY
|
||||
tristate "Drivers for the Microsemi PHYs"
|
||||
---help---
|
||||
Currently supports the VSC8531 and VSC8541 PHYs
|
||||
|
||||
endif # PHYLIB
|
||||
|
||||
config MICREL_KS8995MA
|
||||
|
|
|
@ -11,6 +11,7 @@ obj-$(CONFIG_CICADA_PHY) += cicada.o
|
|||
obj-$(CONFIG_LXT_PHY) += lxt.o
|
||||
obj-$(CONFIG_QSEMI_PHY) += qsemi.o
|
||||
obj-$(CONFIG_SMSC_PHY) += smsc.o
|
||||
obj-$(CONFIG_MICROSEMI_PHY) += mscc.o
|
||||
obj-$(CONFIG_TERANETICS_PHY) += teranetics.o
|
||||
obj-$(CONFIG_VITESSE_PHY) += vitesse.o
|
||||
obj-$(CONFIG_BCM_NET_PHYLIB) += bcm-phy-lib.o
|
||||
|
|
|
@ -0,0 +1,161 @@
|
|||
/*
|
||||
* Driver for Microsemi VSC85xx PHYs
|
||||
*
|
||||
* Author: Nagaraju Lakkaraju
|
||||
* License: Dual MIT/GPL
|
||||
* Copyright (c) 2016 Microsemi Corporation
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/mdio.h>
|
||||
#include <linux/mii.h>
|
||||
#include <linux/phy.h>
|
||||
|
||||
enum rgmii_rx_clock_delay {
|
||||
RGMII_RX_CLK_DELAY_0_2_NS = 0,
|
||||
RGMII_RX_CLK_DELAY_0_8_NS = 1,
|
||||
RGMII_RX_CLK_DELAY_1_1_NS = 2,
|
||||
RGMII_RX_CLK_DELAY_1_7_NS = 3,
|
||||
RGMII_RX_CLK_DELAY_2_0_NS = 4,
|
||||
RGMII_RX_CLK_DELAY_2_3_NS = 5,
|
||||
RGMII_RX_CLK_DELAY_2_6_NS = 6,
|
||||
RGMII_RX_CLK_DELAY_3_4_NS = 7
|
||||
};
|
||||
|
||||
#define MII_VSC85XX_INT_MASK 25
|
||||
#define MII_VSC85XX_INT_MASK_MASK 0xa000
|
||||
#define MII_VSC85XX_INT_STATUS 26
|
||||
|
||||
#define MSCC_EXT_PAGE_ACCESS 31
|
||||
#define MSCC_PHY_PAGE_STANDARD 0x0000 /* Standard registers */
|
||||
#define MSCC_PHY_PAGE_EXTENDED_2 0x0002 /* Extended reg - page 2 */
|
||||
|
||||
/* Extended Page 2 Registers */
|
||||
#define MSCC_PHY_RGMII_CNTL 20
|
||||
#define RGMII_RX_CLK_DELAY_MASK 0x0070
|
||||
#define RGMII_RX_CLK_DELAY_POS 4
|
||||
|
||||
/* Microsemi PHY ID's */
|
||||
#define PHY_ID_VSC8531 0x00070570
|
||||
#define PHY_ID_VSC8541 0x00070770
|
||||
|
||||
static int vsc85xx_phy_page_set(struct phy_device *phydev, u8 page)
|
||||
{
|
||||
int rc;
|
||||
|
||||
rc = phy_write(phydev, MSCC_EXT_PAGE_ACCESS, page);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int vsc85xx_default_config(struct phy_device *phydev)
|
||||
{
|
||||
int rc;
|
||||
u16 reg_val;
|
||||
|
||||
mutex_lock(&phydev->lock);
|
||||
rc = vsc85xx_phy_page_set(phydev, MSCC_PHY_PAGE_EXTENDED_2);
|
||||
if (rc != 0)
|
||||
goto out_unlock;
|
||||
|
||||
reg_val = phy_read(phydev, MSCC_PHY_RGMII_CNTL);
|
||||
reg_val &= ~(RGMII_RX_CLK_DELAY_MASK);
|
||||
reg_val |= (RGMII_RX_CLK_DELAY_1_1_NS << RGMII_RX_CLK_DELAY_POS);
|
||||
phy_write(phydev, MSCC_PHY_RGMII_CNTL, reg_val);
|
||||
rc = vsc85xx_phy_page_set(phydev, MSCC_PHY_PAGE_STANDARD);
|
||||
|
||||
out_unlock:
|
||||
mutex_unlock(&phydev->lock);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int vsc85xx_config_init(struct phy_device *phydev)
|
||||
{
|
||||
int rc;
|
||||
|
||||
rc = vsc85xx_default_config(phydev);
|
||||
if (rc)
|
||||
return rc;
|
||||
rc = genphy_config_init(phydev);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int vsc85xx_ack_interrupt(struct phy_device *phydev)
|
||||
{
|
||||
int rc;
|
||||
|
||||
if (phydev->interrupts == PHY_INTERRUPT_ENABLED)
|
||||
rc = phy_read(phydev, MII_VSC85XX_INT_STATUS);
|
||||
|
||||
return (rc < 0) ? rc : 0;
|
||||
}
|
||||
|
||||
static int vsc85xx_config_intr(struct phy_device *phydev)
|
||||
{
|
||||
int rc;
|
||||
|
||||
if (phydev->interrupts == PHY_INTERRUPT_ENABLED) {
|
||||
rc = phy_write(phydev, MII_VSC85XX_INT_MASK,
|
||||
MII_VSC85XX_INT_MASK_MASK);
|
||||
} else {
|
||||
rc = phy_write(phydev, MII_VSC85XX_INT_MASK, 0);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
rc = phy_read(phydev, MII_VSC85XX_INT_STATUS);
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* Microsemi VSC85xx PHYs */
|
||||
static struct phy_driver vsc85xx_driver[] = {
|
||||
{
|
||||
.phy_id = PHY_ID_VSC8531,
|
||||
.name = "Microsemi VSC8531",
|
||||
.phy_id_mask = 0xfffffff0,
|
||||
.features = PHY_GBIT_FEATURES,
|
||||
.flags = PHY_HAS_INTERRUPT,
|
||||
.soft_reset = &genphy_soft_reset,
|
||||
.config_init = &vsc85xx_config_init,
|
||||
.config_aneg = &genphy_config_aneg,
|
||||
.aneg_done = &genphy_aneg_done,
|
||||
.read_status = &genphy_read_status,
|
||||
.ack_interrupt = &vsc85xx_ack_interrupt,
|
||||
.config_intr = &vsc85xx_config_intr,
|
||||
.suspend = &genphy_suspend,
|
||||
.resume = &genphy_resume,
|
||||
},
|
||||
{
|
||||
.phy_id = PHY_ID_VSC8541,
|
||||
.name = "Microsemi VSC8541 SyncE",
|
||||
.phy_id_mask = 0xfffffff0,
|
||||
.features = PHY_GBIT_FEATURES,
|
||||
.flags = PHY_HAS_INTERRUPT,
|
||||
.soft_reset = &genphy_soft_reset,
|
||||
.config_init = &vsc85xx_config_init,
|
||||
.config_aneg = &genphy_config_aneg,
|
||||
.aneg_done = &genphy_aneg_done,
|
||||
.read_status = &genphy_read_status,
|
||||
.ack_interrupt = &vsc85xx_ack_interrupt,
|
||||
.config_intr = &vsc85xx_config_intr,
|
||||
.suspend = &genphy_suspend,
|
||||
.resume = &genphy_resume,
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
module_phy_driver(vsc85xx_driver);
|
||||
|
||||
static struct mdio_device_id __maybe_unused vsc85xx_tbl[] = {
|
||||
{ PHY_ID_VSC8531, 0xfffffff0, },
|
||||
{ PHY_ID_VSC8541, 0xfffffff0, },
|
||||
{ }
|
||||
};
|
||||
|
||||
MODULE_DEVICE_TABLE(mdio, vsc85xx_tbl);
|
||||
|
||||
MODULE_DESCRIPTION("Microsemi VSC85xx PHY driver");
|
||||
MODULE_AUTHOR("Nagaraju Lakkaraju");
|
||||
MODULE_LICENSE("Dual MIT/GPL");
|
Loading…
Reference in New Issue