-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
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>
- Loading branch information
Raju Lakkaraju
authored and
David S. Miller
committed
Aug 8, 2016
1 parent
07bf2e1
commit d50736a
Showing
3 changed files
with
167 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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"); |