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 253761a0e61b7. 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: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
148b1da886
@ -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
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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,15 +281,23 @@ 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);
|
||||
if (ret) {
|
||||
mdiobus_free(bus);
|
||||
lp->mii_bus = NULL;
|
||||
return ret;
|
||||
}
|
||||
axienet_mdio_mdc_disable(lp);
|
||||
return 0;
|
||||
|
||||
unregister_mdio_enabled:
|
||||
axienet_mdio_mdc_disable(lp);
|
||||
unregister:
|
||||
of_node_put(mdio_node);
|
||||
mdiobus_free(bus);
|
||||
lp->mii_bus = NULL;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
|
Loading…
x
Reference in New Issue
Block a user