Commit 148b1da8 authored by David S. Miller's avatar David S. Miller
Browse files

Merge branch 'axiennet-mdio-bus-freq'



Andy Chiu says:

====================
net: axienet: Use a DT property to configure frequency of the MDIO bus

Some FPGA platforms have to set frequency of the MDIO bus lower than 2.5
MHz. Thus, we use a DT property, which is "clock-frequency", to work
with it at boot time. The default 2.5 MHz would be set if the property
is not pressent. Also, factor out mdio enable/disable functions due to
the api change since 253761a0.

Changelog:
--- v5 ---
1. Make dt-binding patch prior to the implementation patch.
2. Disable mdio bus in error path.
3. Update description of some functions.
--- v4 ---
1. change MAX_MDIO_FREQ to DEFAULT_MDIO_FREQ as suggested by Andrew.
--- v3 RESEND ---
1. Repost the exact same patch again
--- v3 ---
1. Fix coding style, and make probing of the driver fail if MDC overflow
--- v2 ---
1. Use clock-frequency, as defined in mdio.yaml, to configure MDIO
   clock.
2. Only print out frequency if it is set to a non-standard value.
3. Reduce the scope of axienet_mdio_enable and remove
   axienet_mdio_disable because no one really uses it anymore.
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 62a45b38 2e1f2c10
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -68,6 +68,8 @@ Optional properties:
 - mdio		: Child node for MDIO bus. Must be defined if PHY access is
		  required through the core's MDIO interface (i.e. always,
		  unless the PHY is accessed through a different bus).
		  Non-standard MDIO bus frequency is supported via
		  "clock-frequency", see mdio.yaml.

 - pcs-handle: 	  Phandle to the internal PCS/PMA PHY in SGMII or 1000Base-X
		  modes, where "pcs-handle" should be used to point
+0 −2
Original line number Diff line number Diff line
@@ -611,8 +611,6 @@ static inline void axienet_dma_out_addr(struct axienet_local *lp, off_t reg,
#endif /* CONFIG_64BIT */

/* Function prototypes visible in xilinx_axienet_mdio.c for other files */
int axienet_mdio_enable(struct axienet_local *lp);
void axienet_mdio_disable(struct axienet_local *lp);
int axienet_mdio_setup(struct axienet_local *lp);
void axienet_mdio_teardown(struct axienet_local *lp);

+48 −31
Original line number Diff line number Diff line
@@ -17,7 +17,7 @@

#include "xilinx_axienet.h"

#define MAX_MDIO_FREQ		2500000 /* 2.5 MHz */
#define DEFAULT_MDIO_FREQ	2500000 /* 2.5 MHz */
#define DEFAULT_HOST_CLOCK	150000000 /* 150 MHz */

/* Wait till MDIO interface is ready to accept a new transaction.*/
@@ -147,15 +147,20 @@ static int axienet_mdio_write(struct mii_bus *bus, int phy_id, int reg,
/**
 * axienet_mdio_enable - MDIO hardware setup function
 * @lp:		Pointer to axienet local data structure.
 * @np:		Pointer to mdio device tree node.
 *
 * Return:	0 on success, -ETIMEDOUT on a timeout.
 * Return:	0 on success, -ETIMEDOUT on a timeout, -EOVERFLOW on a clock
 *		divisor overflow.
 *
 * Sets up the MDIO interface by initializing the MDIO clock and enabling the
 * MDIO interface in hardware.
 **/
int axienet_mdio_enable(struct axienet_local *lp)
static int axienet_mdio_enable(struct axienet_local *lp, struct device_node *np)
{
	u32 mdio_freq = DEFAULT_MDIO_FREQ;
	u32 host_clock;
	u32 clk_div;
	int ret;

	lp->mii_clk_div = 0;

@@ -184,6 +189,12 @@ int axienet_mdio_enable(struct axienet_local *lp)
			    host_clock);
	}

	if (np)
		of_property_read_u32(np, "clock-frequency", &mdio_freq);
	if (mdio_freq != DEFAULT_MDIO_FREQ)
		netdev_info(lp->ndev, "Setting non-standard mdio bus frequency to %u Hz\n",
			    mdio_freq);

	/* clk_div can be calculated by deriving it from the equation:
	 * fMDIO = fHOST / ((1 + clk_div) * 2)
	 *
@@ -209,40 +220,42 @@ int axienet_mdio_enable(struct axienet_local *lp)
	 * "clock-frequency" from the CPU
	 */

	lp->mii_clk_div = (host_clock / (MAX_MDIO_FREQ * 2)) - 1;
	clk_div = (host_clock / (mdio_freq * 2)) - 1;
	/* If there is any remainder from the division of
	 * fHOST / (MAX_MDIO_FREQ * 2), then we need to add
	 * 1 to the clock divisor or we will surely be above 2.5 MHz
	 * fHOST / (mdio_freq * 2), then we need to add
	 * 1 to the clock divisor or we will surely be
	 * above the requested frequency
	 */
	if (host_clock % (MAX_MDIO_FREQ * 2))
		lp->mii_clk_div++;
	if (host_clock % (mdio_freq * 2))
		clk_div++;

	/* Check for overflow of mii_clk_div */
	if (clk_div & ~XAE_MDIO_MC_CLOCK_DIVIDE_MAX) {
		netdev_warn(lp->ndev, "MDIO clock divisor overflow\n");
		return -EOVERFLOW;
	}
	lp->mii_clk_div = (u8)clk_div;

	netdev_dbg(lp->ndev,
		   "Setting MDIO clock divisor to %u/%u Hz host clock.\n",
		   lp->mii_clk_div, host_clock);

	axienet_iow(lp, XAE_MDIO_MC_OFFSET, lp->mii_clk_div | XAE_MDIO_MC_MDIOEN_MASK);
	axienet_mdio_mdc_enable(lp);

	return axienet_mdio_wait_until_ready(lp);
}
	ret = axienet_mdio_wait_until_ready(lp);
	if (ret)
		axienet_mdio_mdc_disable(lp);

/**
 * axienet_mdio_disable - MDIO hardware disable function
 * @lp:		Pointer to axienet local data structure.
 *
 * Disable the MDIO interface in hardware.
 **/
void axienet_mdio_disable(struct axienet_local *lp)
{
	axienet_iow(lp, XAE_MDIO_MC_OFFSET, 0);
	return ret;
}

/**
 * axienet_mdio_setup - MDIO setup function
 * @lp:		Pointer to axienet local data structure.
 *
 * Return:	0 on success, -ETIMEDOUT on a timeout, -ENOMEM when
 *		mdiobus_alloc (to allocate memory for mii bus structure) fails.
 * Return:	0 on success, -ETIMEDOUT on a timeout, -EOVERFLOW on a clock
 *		divisor overflow, -ENOMEM when mdiobus_alloc (to allocate
 *		memory for mii bus structure) fails.
 *
 * Sets up the MDIO interface by initializing the MDIO clock.
 * Register the MDIO interface.
@@ -253,10 +266,6 @@ int axienet_mdio_setup(struct axienet_local *lp)
	struct mii_bus *bus;
	int ret;

	ret = axienet_mdio_enable(lp);
	if (ret < 0)
		return ret;

	bus = mdiobus_alloc();
	if (!bus)
		return -ENOMEM;
@@ -272,16 +281,24 @@ int axienet_mdio_setup(struct axienet_local *lp)
	lp->mii_bus = bus;

	mdio_node = of_get_child_by_name(lp->dev->of_node, "mdio");
	ret = axienet_mdio_enable(lp, mdio_node);
	if (ret < 0)
		goto unregister;
	ret = of_mdiobus_register(bus, mdio_node);
	if (ret)
		goto unregister_mdio_enabled;
	of_node_put(mdio_node);
	axienet_mdio_mdc_disable(lp);
	return 0;

unregister_mdio_enabled:
	axienet_mdio_mdc_disable(lp);
unregister:
	of_node_put(mdio_node);
	if (ret) {
	mdiobus_free(bus);
	lp->mii_bus = NULL;
	return ret;
}
	axienet_mdio_mdc_disable(lp);
	return 0;
}

/**
 * axienet_mdio_teardown - MDIO remove function