-
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.
David Daney says: ==================== net/phy: Improvements to Cavium Thunder MDIO code. Changes from v1: - In 1/3 Add back check for non-OF objects in bgx_init_of_phy(). It is probably not necessary, but better safe than sorry... The firmware on many Cavium Thunder systems configures the MDIO bus hardware to be probed as a PCI device. In order to use the MDIO bus drivers in this configuration, we must add PCI probing to the driver. There are two parts to this set of three patches: 1) Cleanup the PHY probing code in thunder_bgx.c to handle the case where there is no PHY attached to a port, as well as being more robust in the face of driver loading order by use of -EPROBE_DEFER. 2) Split mdio-octeon.c into two drivers, one with platform probing, and the other with PCI probing. Common code is shared between the two. Tested on several different Thunder and OCTEON systems, also compile tested on x86_64. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
- Loading branch information
Showing
8 changed files
with
535 additions
and
281 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
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,149 @@ | ||
/* | ||
* This file is subject to the terms and conditions of the GNU General Public | ||
* License. See the file "COPYING" in the main directory of this archive | ||
* for more details. | ||
* | ||
* Copyright (C) 2009-2016 Cavium, Inc. | ||
*/ | ||
|
||
#include <linux/delay.h> | ||
#include <linux/module.h> | ||
#include <linux/phy.h> | ||
#include <linux/io.h> | ||
|
||
#include "mdio-cavium.h" | ||
|
||
static void cavium_mdiobus_set_mode(struct cavium_mdiobus *p, | ||
enum cavium_mdiobus_mode m) | ||
{ | ||
union cvmx_smix_clk smi_clk; | ||
|
||
if (m == p->mode) | ||
return; | ||
|
||
smi_clk.u64 = oct_mdio_readq(p->register_base + SMI_CLK); | ||
smi_clk.s.mode = (m == C45) ? 1 : 0; | ||
smi_clk.s.preamble = 1; | ||
oct_mdio_writeq(smi_clk.u64, p->register_base + SMI_CLK); | ||
p->mode = m; | ||
} | ||
|
||
static int cavium_mdiobus_c45_addr(struct cavium_mdiobus *p, | ||
int phy_id, int regnum) | ||
{ | ||
union cvmx_smix_cmd smi_cmd; | ||
union cvmx_smix_wr_dat smi_wr; | ||
int timeout = 1000; | ||
|
||
cavium_mdiobus_set_mode(p, C45); | ||
|
||
smi_wr.u64 = 0; | ||
smi_wr.s.dat = regnum & 0xffff; | ||
oct_mdio_writeq(smi_wr.u64, p->register_base + SMI_WR_DAT); | ||
|
||
regnum = (regnum >> 16) & 0x1f; | ||
|
||
smi_cmd.u64 = 0; | ||
smi_cmd.s.phy_op = 0; /* MDIO_CLAUSE_45_ADDRESS */ | ||
smi_cmd.s.phy_adr = phy_id; | ||
smi_cmd.s.reg_adr = regnum; | ||
oct_mdio_writeq(smi_cmd.u64, p->register_base + SMI_CMD); | ||
|
||
do { | ||
/* Wait 1000 clocks so we don't saturate the RSL bus | ||
* doing reads. | ||
*/ | ||
__delay(1000); | ||
smi_wr.u64 = oct_mdio_readq(p->register_base + SMI_WR_DAT); | ||
} while (smi_wr.s.pending && --timeout); | ||
|
||
if (timeout <= 0) | ||
return -EIO; | ||
return 0; | ||
} | ||
|
||
int cavium_mdiobus_read(struct mii_bus *bus, int phy_id, int regnum) | ||
{ | ||
struct cavium_mdiobus *p = bus->priv; | ||
union cvmx_smix_cmd smi_cmd; | ||
union cvmx_smix_rd_dat smi_rd; | ||
unsigned int op = 1; /* MDIO_CLAUSE_22_READ */ | ||
int timeout = 1000; | ||
|
||
if (regnum & MII_ADDR_C45) { | ||
int r = cavium_mdiobus_c45_addr(p, phy_id, regnum); | ||
|
||
if (r < 0) | ||
return r; | ||
|
||
regnum = (regnum >> 16) & 0x1f; | ||
op = 3; /* MDIO_CLAUSE_45_READ */ | ||
} else { | ||
cavium_mdiobus_set_mode(p, C22); | ||
} | ||
|
||
smi_cmd.u64 = 0; | ||
smi_cmd.s.phy_op = op; | ||
smi_cmd.s.phy_adr = phy_id; | ||
smi_cmd.s.reg_adr = regnum; | ||
oct_mdio_writeq(smi_cmd.u64, p->register_base + SMI_CMD); | ||
|
||
do { | ||
/* Wait 1000 clocks so we don't saturate the RSL bus | ||
* doing reads. | ||
*/ | ||
__delay(1000); | ||
smi_rd.u64 = oct_mdio_readq(p->register_base + SMI_RD_DAT); | ||
} while (smi_rd.s.pending && --timeout); | ||
|
||
if (smi_rd.s.val) | ||
return smi_rd.s.dat; | ||
else | ||
return -EIO; | ||
} | ||
EXPORT_SYMBOL(cavium_mdiobus_read); | ||
|
||
int cavium_mdiobus_write(struct mii_bus *bus, int phy_id, int regnum, u16 val) | ||
{ | ||
struct cavium_mdiobus *p = bus->priv; | ||
union cvmx_smix_cmd smi_cmd; | ||
union cvmx_smix_wr_dat smi_wr; | ||
unsigned int op = 0; /* MDIO_CLAUSE_22_WRITE */ | ||
int timeout = 1000; | ||
|
||
if (regnum & MII_ADDR_C45) { | ||
int r = cavium_mdiobus_c45_addr(p, phy_id, regnum); | ||
|
||
if (r < 0) | ||
return r; | ||
|
||
regnum = (regnum >> 16) & 0x1f; | ||
op = 1; /* MDIO_CLAUSE_45_WRITE */ | ||
} else { | ||
cavium_mdiobus_set_mode(p, C22); | ||
} | ||
|
||
smi_wr.u64 = 0; | ||
smi_wr.s.dat = val; | ||
oct_mdio_writeq(smi_wr.u64, p->register_base + SMI_WR_DAT); | ||
|
||
smi_cmd.u64 = 0; | ||
smi_cmd.s.phy_op = op; | ||
smi_cmd.s.phy_adr = phy_id; | ||
smi_cmd.s.reg_adr = regnum; | ||
oct_mdio_writeq(smi_cmd.u64, p->register_base + SMI_CMD); | ||
|
||
do { | ||
/* Wait 1000 clocks so we don't saturate the RSL bus | ||
* doing reads. | ||
*/ | ||
__delay(1000); | ||
smi_wr.u64 = oct_mdio_readq(p->register_base + SMI_WR_DAT); | ||
} while (smi_wr.s.pending && --timeout); | ||
|
||
if (timeout <= 0) | ||
return -EIO; | ||
|
||
return 0; | ||
} | ||
EXPORT_SYMBOL(cavium_mdiobus_write); |
Oops, something went wrong.