Skip to content

Commit

Permalink
net/phy: micrel: Add clock support for KSZ8021/KSZ8031
Browse files Browse the repository at this point in the history
The KSZ8021 and KSZ8031 support RMII reference input clocks of 25MHz
and 50MHz. Both PHYs differ in the default frequency they expect
after reset. If this differs from the actual input clock, then
register 0x1f bit 7 must be changed.

Signed-off-by: Sascha Hauer <[email protected]>
Reviewed-by: Florian Fainelli <[email protected]>
Signed-off-by: David S. Miller <[email protected]>
  • Loading branch information
saschahauer authored and davem330 committed Oct 10, 2014
1 parent 5af7fb6 commit 1fadee0
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 2 deletions.
6 changes: 6 additions & 0 deletions Documentation/devicetree/bindings/net/micrel.txt
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,9 @@ Optional properties:
KSZ8051: register 0x1f, bits 5..4

See the respective PHY datasheet for the mode values.

- clocks, clock-names: contains clocks according to the common clock bindings.

supported clocks:
- KSZ8021, KSZ8031: "rmii-ref": The RMII refence input clock. Used
to determine the XI input clock.
31 changes: 29 additions & 2 deletions drivers/net/phy/micrel.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
#include <linux/phy.h>
#include <linux/micrel_phy.h>
#include <linux/of.h>
#include <linux/clk.h>

/* Operation Mode Strap Override */
#define MII_KSZPHY_OMSO 0x16
Expand Down Expand Up @@ -72,9 +73,12 @@ static int ksz_config_flags(struct phy_device *phydev)
{
int regval;

if (phydev->dev_flags & MICREL_PHY_50MHZ_CLK) {
if (phydev->dev_flags & (MICREL_PHY_50MHZ_CLK | MICREL_PHY_25MHZ_CLK)) {
regval = phy_read(phydev, MII_KSZPHY_CTRL);
regval |= KSZ8051_RMII_50MHZ_CLK;
if (phydev->dev_flags & MICREL_PHY_50MHZ_CLK)
regval |= KSZ8051_RMII_50MHZ_CLK;
else
regval &= ~KSZ8051_RMII_50MHZ_CLK;
return phy_write(phydev, MII_KSZPHY_CTRL, regval);
}
return 0;
Expand Down Expand Up @@ -440,6 +444,27 @@ ksz9021_wr_mmd_phyreg(struct phy_device *phydev, int ptrad, int devnum,
{
}

static int ksz8021_probe(struct phy_device *phydev)
{
struct clk *clk;

clk = devm_clk_get(&phydev->dev, "rmii-ref");
if (!IS_ERR(clk)) {
unsigned long rate = clk_get_rate(clk);

if (rate > 24500000 && rate < 25500000) {
phydev->dev_flags |= MICREL_PHY_25MHZ_CLK;
} else if (rate > 49500000 && rate < 50500000) {
phydev->dev_flags |= MICREL_PHY_50MHZ_CLK;
} else {
dev_err(&phydev->dev, "Clock rate out of range: %ld\n", rate);
return -EINVAL;
}
}

return 0;
}

static struct phy_driver ksphy_driver[] = {
{
.phy_id = PHY_ID_KS8737,
Expand All @@ -462,6 +487,7 @@ static struct phy_driver ksphy_driver[] = {
.features = (PHY_BASIC_FEATURES | SUPPORTED_Pause |
SUPPORTED_Asym_Pause),
.flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
.probe = ksz8021_probe,
.config_init = ksz8021_config_init,
.config_aneg = genphy_config_aneg,
.read_status = genphy_read_status,
Expand All @@ -477,6 +503,7 @@ static struct phy_driver ksphy_driver[] = {
.features = (PHY_BASIC_FEATURES | SUPPORTED_Pause |
SUPPORTED_Asym_Pause),
.flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
.probe = ksz8021_probe,
.config_init = ksz8021_config_init,
.config_aneg = genphy_config_aneg,
.read_status = genphy_read_status,
Expand Down
1 change: 1 addition & 0 deletions include/linux/micrel_phy.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@

/* struct phy_device dev_flags definitions */
#define MICREL_PHY_50MHZ_CLK 0x00000001
#define MICREL_PHY_25MHZ_CLK 0x00000002

#define MICREL_KSZ9021_EXTREG_CTRL 0xB
#define MICREL_KSZ9021_EXTREG_DATA_WRITE 0xC
Expand Down

0 comments on commit 1fadee0

Please sign in to comment.