Skip to content

Commit

Permalink
net: mdio: Add the reset function for IPQ MDIO driver
Browse files Browse the repository at this point in the history
1. configure the MDIO clock source frequency.
2. the LDO resource is needed to configure the ethernet LDO available
for CMN_PLL.

Signed-off-by: Luo Jie <luoj@codeaurora.org>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Luo Jie authored and davem330 committed Aug 16, 2021
1 parent e4637f6 commit 23a890d
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 0 deletions.
1 change: 1 addition & 0 deletions drivers/net/mdio/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,7 @@ config MDIO_OCTEON
config MDIO_IPQ4019
tristate "Qualcomm IPQ4019 MDIO interface support"
depends on HAS_IOMEM && OF_MDIO
depends on COMMON_CLK
help
This driver supports the MDIO interface found in Qualcomm
IPQ40xx series Soc-s.
Expand Down
43 changes: 43 additions & 0 deletions drivers/net/mdio/mdio-ipq4019.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include <linux/of_mdio.h>
#include <linux/phy.h>
#include <linux/platform_device.h>
#include <linux/clk.h>

#define MDIO_MODE_REG 0x40
#define MDIO_ADDR_REG 0x44
Expand All @@ -31,8 +32,15 @@
#define IPQ4019_MDIO_TIMEOUT 10000
#define IPQ4019_MDIO_SLEEP 10

/* MDIO clock source frequency is fixed to 100M */
#define IPQ_MDIO_CLK_RATE 100000000

#define IPQ_PHY_SET_DELAY_US 100000

struct ipq4019_mdio_data {
void __iomem *membase;
void __iomem *eth_ldo_rdy;
struct clk *mdio_clk;
};

static int ipq4019_mdio_wait_busy(struct mii_bus *bus)
Expand Down Expand Up @@ -171,10 +179,35 @@ static int ipq4019_mdio_write(struct mii_bus *bus, int mii_id, int regnum,
return 0;
}

static int ipq_mdio_reset(struct mii_bus *bus)
{
struct ipq4019_mdio_data *priv = bus->priv;
u32 val;
int ret;

/* To indicate CMN_PLL that ethernet_ldo has been ready if platform resource 1
* is specified in the device tree.
*/
if (priv->eth_ldo_rdy) {
val = readl(priv->eth_ldo_rdy);
val |= BIT(0);
writel(val, priv->eth_ldo_rdy);
fsleep(IPQ_PHY_SET_DELAY_US);
}

/* Configure MDIO clock source frequency if clock is specified in the device tree */
ret = clk_set_rate(priv->mdio_clk, IPQ_MDIO_CLK_RATE);
if (ret)
return ret;

return clk_prepare_enable(priv->mdio_clk);
}

static int ipq4019_mdio_probe(struct platform_device *pdev)
{
struct ipq4019_mdio_data *priv;
struct mii_bus *bus;
struct resource *res;
int ret;

bus = devm_mdiobus_alloc_size(&pdev->dev, sizeof(*priv));
Expand All @@ -187,9 +220,19 @@ static int ipq4019_mdio_probe(struct platform_device *pdev)
if (IS_ERR(priv->membase))
return PTR_ERR(priv->membase);

priv->mdio_clk = devm_clk_get_optional(&pdev->dev, "gcc_mdio_ahb_clk");
if (IS_ERR(priv->mdio_clk))
return PTR_ERR(priv->mdio_clk);

/* The platform resource is provided on the chipset IPQ5018 */
res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
if (res)
priv->eth_ldo_rdy = devm_ioremap_resource(&pdev->dev, res);

bus->name = "ipq4019_mdio";
bus->read = ipq4019_mdio_read;
bus->write = ipq4019_mdio_write;
bus->reset = ipq_mdio_reset;
bus->parent = &pdev->dev;
snprintf(bus->id, MII_BUS_ID_SIZE, "%s%d", pdev->name, pdev->id);

Expand Down

0 comments on commit 23a890d

Please sign in to comment.