Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1fadee0c authored by Sascha Hauer's avatar Sascha Hauer Committed by David S. Miller
Browse files

net/phy: micrel: Add clock support for KSZ8021/KSZ8031



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: default avatarSascha Hauer <s.hauer@pengutronix.de>
Reviewed-by: default avatarFlorian Fainelli <f.fainelli@gmail.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 5af7fb6e
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -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.
+29 −2
Original line number Diff line number Diff line
@@ -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
@@ -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);
		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;
@@ -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,
@@ -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,
@@ -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,
+1 −0
Original line number Diff line number Diff line
@@ -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