summaryrefslogtreecommitdiff
path: root/drivers/net/mdio/mdio-mux-bcm-iproc.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/mdio/mdio-mux-bcm-iproc.c')
-rw-r--r--drivers/net/mdio/mdio-mux-bcm-iproc.c64
1 files changed, 48 insertions, 16 deletions
diff --git a/drivers/net/mdio/mdio-mux-bcm-iproc.c b/drivers/net/mdio/mdio-mux-bcm-iproc.c
index 014c0baedbd2..8ba0917a930a 100644
--- a/drivers/net/mdio/mdio-mux-bcm-iproc.c
+++ b/drivers/net/mdio/mdio-mux-bcm-iproc.c
@@ -2,6 +2,7 @@
/*
* Copyright 2016 Broadcom
*/
+#include <linux/align.h>
#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/device.h>
@@ -11,6 +12,7 @@
#include <linux/of_mdio.h>
#include <linux/phy.h>
#include <linux/platform_device.h>
+#include <linux/sizes.h>
#define MDIO_RATE_ADJ_EXT_OFFSET 0x000
#define MDIO_RATE_ADJ_INT_OFFSET 0x004
@@ -98,7 +100,7 @@ static int iproc_mdio_wait_for_idle(void __iomem *base, bool result)
* Return value: Successful Read operation returns read reg values and write
* operation returns 0. Failure operation returns negative error code.
*/
-static int start_miim_ops(void __iomem *base,
+static int start_miim_ops(void __iomem *base, bool c45,
u16 phyid, u32 reg, u16 val, u32 op)
{
u32 param;
@@ -112,7 +114,7 @@ static int start_miim_ops(void __iomem *base,
param = readl(base + MDIO_PARAM_OFFSET);
param |= phyid << MDIO_PARAM_PHY_ID;
param |= val << MDIO_PARAM_PHY_DATA;
- if (reg & MII_ADDR_C45)
+ if (c45)
param |= BIT(MDIO_PARAM_C45_SEL);
writel(param, base + MDIO_PARAM_OFFSET);
@@ -131,28 +133,58 @@ err:
return ret;
}
-static int iproc_mdiomux_read(struct mii_bus *bus, int phyid, int reg)
+static int iproc_mdiomux_read_c22(struct mii_bus *bus, int phyid, int reg)
{
struct iproc_mdiomux_desc *md = bus->priv;
int ret;
- ret = start_miim_ops(md->base, phyid, reg, 0, MDIO_CTRL_READ_OP);
+ ret = start_miim_ops(md->base, false, phyid, reg, 0, MDIO_CTRL_READ_OP);
if (ret < 0)
- dev_err(&bus->dev, "mdiomux read operation failed!!!");
+ dev_err(&bus->dev, "mdiomux c22 read operation failed!!!");
return ret;
}
-static int iproc_mdiomux_write(struct mii_bus *bus,
- int phyid, int reg, u16 val)
+static int iproc_mdiomux_read_c45(struct mii_bus *bus, int phyid, int devad,
+ int reg)
+{
+ struct iproc_mdiomux_desc *md = bus->priv;
+ int ret;
+
+ ret = start_miim_ops(md->base, true, phyid, reg | devad << 16, 0,
+ MDIO_CTRL_READ_OP);
+ if (ret < 0)
+ dev_err(&bus->dev, "mdiomux read c45 operation failed!!!");
+
+ return ret;
+}
+
+static int iproc_mdiomux_write_c22(struct mii_bus *bus,
+ int phyid, int reg, u16 val)
{
struct iproc_mdiomux_desc *md = bus->priv;
int ret;
/* Write val at reg offset */
- ret = start_miim_ops(md->base, phyid, reg, val, MDIO_CTRL_WRITE_OP);
+ ret = start_miim_ops(md->base, false, phyid, reg, val,
+ MDIO_CTRL_WRITE_OP);
if (ret < 0)
- dev_err(&bus->dev, "mdiomux write operation failed!!!");
+ dev_err(&bus->dev, "mdiomux write c22 operation failed!!!");
+
+ return ret;
+}
+
+static int iproc_mdiomux_write_c45(struct mii_bus *bus,
+ int phyid, int devad, int reg, u16 val)
+{
+ struct iproc_mdiomux_desc *md = bus->priv;
+ int ret;
+
+ /* Write val at reg offset */
+ ret = start_miim_ops(md->base, true, phyid, reg | devad << 16, val,
+ MDIO_CTRL_WRITE_OP);
+ if (ret < 0)
+ dev_err(&bus->dev, "mdiomux write c45 operation failed!!!");
return ret;
}
@@ -190,12 +222,12 @@ static int mdio_mux_iproc_probe(struct platform_device *pdev)
md->base = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
if (IS_ERR(md->base))
return PTR_ERR(md->base);
- if (res->start & 0xfff) {
+ if (!IS_ALIGNED(res->start, SZ_4K)) {
/* For backward compatibility in case the
* base address is specified with an offset.
*/
dev_info(&pdev->dev, "fix base address in dt-blob\n");
- res->start &= ~0xfff;
+ res->start = ALIGN_DOWN(res->start, SZ_4K);
res->end = res->start + MDIO_REG_ADDR_SPACE_SIZE - 1;
}
@@ -223,8 +255,10 @@ static int mdio_mux_iproc_probe(struct platform_device *pdev)
bus->name = "iProc MDIO mux bus";
snprintf(bus->id, MII_BUS_ID_SIZE, "%s-%d", pdev->name, pdev->id);
bus->parent = &pdev->dev;
- bus->read = iproc_mdiomux_read;
- bus->write = iproc_mdiomux_write;
+ bus->read = iproc_mdiomux_read_c22;
+ bus->write = iproc_mdiomux_write_c22;
+ bus->read_c45 = iproc_mdiomux_read_c45;
+ bus->write_c45 = iproc_mdiomux_write_c45;
bus->phy_mask = ~0;
bus->dev.of_node = pdev->dev.of_node;
@@ -255,15 +289,13 @@ out_clk:
return rc;
}
-static int mdio_mux_iproc_remove(struct platform_device *pdev)
+static void mdio_mux_iproc_remove(struct platform_device *pdev)
{
struct iproc_mdiomux_desc *md = platform_get_drvdata(pdev);
mdio_mux_uninit(md->mux_handle);
mdiobus_unregister(md->mii_bus);
clk_disable_unprepare(md->core_clk);
-
- return 0;
}
#ifdef CONFIG_PM_SLEEP