Commit a198c142 authored by Yaniv Rosner's avatar Yaniv Rosner Committed by David S. Miller

bnx2x: Improve cl45 access methods

Instead of setting CL45 mode for every CL45 access, apply it once during initialization.
Signed-off-by: default avatarYaniv Rosner <yanivr@broadcom.com>
Signed-off-by: default avatarEilon Greenstein <eilong@broadcom.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent ec146a6f
...@@ -464,6 +464,29 @@ void bnx2x_pfc_statistic(struct link_params *params, struct link_vars *vars, ...@@ -464,6 +464,29 @@ void bnx2x_pfc_statistic(struct link_params *params, struct link_vars *vars,
/******************************************************************/ /******************************************************************/
/* MAC/PBF section */ /* MAC/PBF section */
/******************************************************************/ /******************************************************************/
static void bnx2x_set_mdio_clk(struct bnx2x *bp, u32 chip_id, u8 port)
{
u32 mode, emac_base;
/**
* Set clause 45 mode, slow down the MDIO clock to 2.5MHz
* (a value of 49==0x31) and make sure that the AUTO poll is off
*/
if (CHIP_IS_E2(bp))
emac_base = GRCBASE_EMAC0;
else
emac_base = (port) ? GRCBASE_EMAC1 : GRCBASE_EMAC0;
mode = REG_RD(bp, emac_base + EMAC_REG_EMAC_MDIO_MODE);
mode &= ~(EMAC_MDIO_MODE_AUTO_POLL |
EMAC_MDIO_MODE_CLOCK_CNT);
mode |= (49L << EMAC_MDIO_MODE_CLOCK_CNT_BITSHIFT);
mode |= (EMAC_MDIO_MODE_CLAUSE_45);
REG_WR(bp, emac_base + EMAC_REG_EMAC_MDIO_MODE, mode);
udelay(40);
}
static void bnx2x_emac_init(struct link_params *params, static void bnx2x_emac_init(struct link_params *params,
struct link_vars *vars) struct link_vars *vars)
{ {
...@@ -495,7 +518,7 @@ static void bnx2x_emac_init(struct link_params *params, ...@@ -495,7 +518,7 @@ static void bnx2x_emac_init(struct link_params *params,
} }
timeout--; timeout--;
} while (val & EMAC_MODE_RESET); } while (val & EMAC_MODE_RESET);
bnx2x_set_mdio_clk(bp, params->chip_id, port);
/* Set mac address */ /* Set mac address */
val = ((params->mac_addr[0] << 8) | val = ((params->mac_addr[0] << 8) |
params->mac_addr[1]); params->mac_addr[1]);
...@@ -1352,144 +1375,113 @@ static u32 bnx2x_get_emac_base(struct bnx2x *bp, ...@@ -1352,144 +1375,113 @@ static u32 bnx2x_get_emac_base(struct bnx2x *bp,
/******************************************************************/ /******************************************************************/
/* CL45 access functions */ /* CL45 access functions */
/******************************************************************/ /******************************************************************/
static int bnx2x_cl45_write(struct bnx2x *bp, struct bnx2x_phy *phy, static int bnx2x_cl45_read(struct bnx2x *bp, struct bnx2x_phy *phy,
u8 devad, u16 reg, u16 val) u8 devad, u16 reg, u16 *ret_val)
{ {
u32 tmp, saved_mode; u32 val;
u8 i; u16 i;
int rc = 0; int rc = 0;
/*
* Set clause 45 mode, slow down the MDIO clock to 2.5MHz
* (a value of 49==0x31) and make sure that the AUTO poll is off
*/
saved_mode = REG_RD(bp, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE);
tmp = saved_mode & ~(EMAC_MDIO_MODE_AUTO_POLL |
EMAC_MDIO_MODE_CLOCK_CNT);
tmp |= (EMAC_MDIO_MODE_CLAUSE_45 |
(49 << EMAC_MDIO_MODE_CLOCK_CNT_BITSHIFT));
REG_WR(bp, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE, tmp);
REG_RD(bp, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE);
udelay(40);
/* address */ /* address */
val = ((phy->addr << 21) | (devad << 16) | reg |
tmp = ((phy->addr << 21) | (devad << 16) | reg |
EMAC_MDIO_COMM_COMMAND_ADDRESS | EMAC_MDIO_COMM_COMMAND_ADDRESS |
EMAC_MDIO_COMM_START_BUSY); EMAC_MDIO_COMM_START_BUSY);
REG_WR(bp, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_COMM, tmp); REG_WR(bp, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_COMM, val);
for (i = 0; i < 50; i++) { for (i = 0; i < 50; i++) {
udelay(10); udelay(10);
tmp = REG_RD(bp, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_COMM); val = REG_RD(bp, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_COMM);
if (!(tmp & EMAC_MDIO_COMM_START_BUSY)) { if (!(val & EMAC_MDIO_COMM_START_BUSY)) {
udelay(5); udelay(5);
break; break;
} }
} }
if (tmp & EMAC_MDIO_COMM_START_BUSY) { if (val & EMAC_MDIO_COMM_START_BUSY) {
DP(NETIF_MSG_LINK, "write phy register failed\n"); DP(NETIF_MSG_LINK, "read phy register failed\n");
netdev_err(bp->dev, "MDC/MDIO access timeout\n"); netdev_err(bp->dev, "MDC/MDIO access timeout\n");
*ret_val = 0;
rc = -EFAULT; rc = -EFAULT;
} else { } else {
/* data */ /* data */
tmp = ((phy->addr << 21) | (devad << 16) | val | val = ((phy->addr << 21) | (devad << 16) |
EMAC_MDIO_COMM_COMMAND_WRITE_45 | EMAC_MDIO_COMM_COMMAND_READ_45 |
EMAC_MDIO_COMM_START_BUSY); EMAC_MDIO_COMM_START_BUSY);
REG_WR(bp, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_COMM, tmp); REG_WR(bp, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_COMM, val);
for (i = 0; i < 50; i++) { for (i = 0; i < 50; i++) {
udelay(10); udelay(10);
tmp = REG_RD(bp, phy->mdio_ctrl + val = REG_RD(bp, phy->mdio_ctrl +
EMAC_REG_EMAC_MDIO_COMM); EMAC_REG_EMAC_MDIO_COMM);
if (!(tmp & EMAC_MDIO_COMM_START_BUSY)) { if (!(val & EMAC_MDIO_COMM_START_BUSY)) {
udelay(5); *ret_val = (u16)(val & EMAC_MDIO_COMM_DATA);
break; break;
} }
} }
if (tmp & EMAC_MDIO_COMM_START_BUSY) { if (val & EMAC_MDIO_COMM_START_BUSY) {
DP(NETIF_MSG_LINK, "write phy register failed\n"); DP(NETIF_MSG_LINK, "read phy register failed\n");
netdev_err(bp->dev, "MDC/MDIO access timeout\n"); netdev_err(bp->dev, "MDC/MDIO access timeout\n");
*ret_val = 0;
rc = -EFAULT; rc = -EFAULT;
} }
} }
/* Restore the saved mode */
REG_WR(bp, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE, saved_mode);
return rc; return rc;
} }
static int bnx2x_cl45_read(struct bnx2x *bp, struct bnx2x_phy *phy, static int bnx2x_cl45_write(struct bnx2x *bp, struct bnx2x_phy *phy,
u8 devad, u16 reg, u16 *ret_val) u8 devad, u16 reg, u16 val)
{ {
u32 val, saved_mode; u32 tmp;
u16 i; u8 i;
int rc = 0; int rc = 0;
/*
* Set clause 45 mode, slow down the MDIO clock to 2.5MHz
* (a value of 49==0x31) and make sure that the AUTO poll is off
*/
saved_mode = REG_RD(bp, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE);
val = saved_mode & ~((EMAC_MDIO_MODE_AUTO_POLL |
EMAC_MDIO_MODE_CLOCK_CNT));
val |= (EMAC_MDIO_MODE_CLAUSE_45 |
(49L << EMAC_MDIO_MODE_CLOCK_CNT_BITSHIFT));
REG_WR(bp, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE, val);
REG_RD(bp, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE);
udelay(40);
/* address */ /* address */
val = ((phy->addr << 21) | (devad << 16) | reg |
tmp = ((phy->addr << 21) | (devad << 16) | reg |
EMAC_MDIO_COMM_COMMAND_ADDRESS | EMAC_MDIO_COMM_COMMAND_ADDRESS |
EMAC_MDIO_COMM_START_BUSY); EMAC_MDIO_COMM_START_BUSY);
REG_WR(bp, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_COMM, val); REG_WR(bp, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_COMM, tmp);
for (i = 0; i < 50; i++) { for (i = 0; i < 50; i++) {
udelay(10); udelay(10);
val = REG_RD(bp, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_COMM); tmp = REG_RD(bp, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_COMM);
if (!(val & EMAC_MDIO_COMM_START_BUSY)) { if (!(tmp & EMAC_MDIO_COMM_START_BUSY)) {
udelay(5); udelay(5);
break; break;
} }
} }
if (val & EMAC_MDIO_COMM_START_BUSY) { if (tmp & EMAC_MDIO_COMM_START_BUSY) {
DP(NETIF_MSG_LINK, "read phy register failed\n"); DP(NETIF_MSG_LINK, "write phy register failed\n");
netdev_err(bp->dev, "MDC/MDIO access timeout\n"); netdev_err(bp->dev, "MDC/MDIO access timeout\n");
*ret_val = 0;
rc = -EFAULT; rc = -EFAULT;
} else { } else {
/* data */ /* data */
val = ((phy->addr << 21) | (devad << 16) | tmp = ((phy->addr << 21) | (devad << 16) | val |
EMAC_MDIO_COMM_COMMAND_READ_45 | EMAC_MDIO_COMM_COMMAND_WRITE_45 |
EMAC_MDIO_COMM_START_BUSY); EMAC_MDIO_COMM_START_BUSY);
REG_WR(bp, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_COMM, val); REG_WR(bp, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_COMM, tmp);
for (i = 0; i < 50; i++) { for (i = 0; i < 50; i++) {
udelay(10); udelay(10);
val = REG_RD(bp, phy->mdio_ctrl + tmp = REG_RD(bp, phy->mdio_ctrl +
EMAC_REG_EMAC_MDIO_COMM); EMAC_REG_EMAC_MDIO_COMM);
if (!(val & EMAC_MDIO_COMM_START_BUSY)) { if (!(tmp & EMAC_MDIO_COMM_START_BUSY)) {
*ret_val = (u16)(val & EMAC_MDIO_COMM_DATA); udelay(5);
break; break;
} }
} }
if (val & EMAC_MDIO_COMM_START_BUSY) { if (tmp & EMAC_MDIO_COMM_START_BUSY) {
DP(NETIF_MSG_LINK, "read phy register failed\n"); DP(NETIF_MSG_LINK, "write phy register failed\n");
netdev_err(bp->dev, "MDC/MDIO access timeout\n"); netdev_err(bp->dev, "MDC/MDIO access timeout\n");
*ret_val = 0;
rc = -EFAULT; rc = -EFAULT;
} }
} }
/* Restore the saved mode */
REG_WR(bp, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE, saved_mode);
return rc; return rc;
} }
...@@ -8425,6 +8417,8 @@ int bnx2x_common_init_phy(struct bnx2x *bp, u32 shmem_base_path[], ...@@ -8425,6 +8417,8 @@ int bnx2x_common_init_phy(struct bnx2x *bp, u32 shmem_base_path[],
u32 phy_ver; u32 phy_ver;
u8 phy_index; u8 phy_index;
u32 ext_phy_type, ext_phy_config; u32 ext_phy_type, ext_phy_config;
bnx2x_set_mdio_clk(bp, chip_id, PORT_0);
bnx2x_set_mdio_clk(bp, chip_id, PORT_1);
DP(NETIF_MSG_LINK, "Begin common phy init\n"); DP(NETIF_MSG_LINK, "Begin common phy init\n");
/* Check if common init was already done */ /* Check if common init was already done */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment