diff mbox

[RFC,4/4] net: mvmdio: add getter and setter for PHY addresses

Message ID 1359108409-4378-5-git-send-email-florian@openwrt.org (mailing list archive)
State New, archived
Headers show

Commit Message

Florian Fainelli Jan. 25, 2013, 10:06 a.m. UTC
This patch adds orion_mdio_{set,get}_phy_addr(.., port_number, phy_addr)
which is a feature available in this MDIO driver to monitor a particular
PHY address. This brings mvmdio one step closer to what is used in
mv643x_eth.

Signed-off-by: Florian Fainelli <florian@openwrt.org>
---
 drivers/net/ethernet/marvell/mvmdio.c |   29 +++++++++++++++++++++++++++++
 include/linux/marvell_mvmdio.h        |   10 ++++++++++
 2 files changed, 39 insertions(+)
 create mode 100644 include/linux/marvell_mvmdio.h

Comments

Jason Gunthorpe Jan. 25, 2013, 6:16 p.m. UTC | #1
On Fri, Jan 25, 2013 at 11:06:49AM +0100, Florian Fainelli wrote:
> This patch adds orion_mdio_{set,get}_phy_addr(.., port_number, phy_addr)
> which is a feature available in this MDIO driver to monitor a particular
> PHY address. This brings mvmdio one step closer to what is used in
> mv643x_eth.

This seems really strange.

Are you sure this should be part of the MDIO driver? Based on my docs,
this register is part of the ethernet controller HW, which
autonomously reads from the phy via MDIO.

It seems cleaner to set this register from the ethernet controller
based on the phy it is using and keep the MDIO driver purely for MDIO
bus access.

It is acceptable to overlap the device address ranges, start the
ethernet controller at 72000 and start the MDIO at 72004, the platform
bus code automatically nests them.

Jason
Florian Fainelli Jan. 25, 2013, 7:58 p.m. UTC | #2
Le 25/01/2013 19:16, Jason Gunthorpe a écrit :
> On Fri, Jan 25, 2013 at 11:06:49AM +0100, Florian Fainelli wrote:
>> This patch adds orion_mdio_{set,get}_phy_addr(.., port_number, phy_addr)
>> which is a feature available in this MDIO driver to monitor a particular
>> PHY address. This brings mvmdio one step closer to what is used in
>> mv643x_eth.
>
> This seems really strange.
>
> Are you sure this should be part of the MDIO driver? Based on my docs,
> this register is part of the ethernet controller HW, which
> autonomously reads from the phy via MDIO.

My reading of the datasheets for 88F628x and Armada 370 says that it 
actually belongs to the MDIO part of the controller (it is just below 
the SMI registers).

>
> It seems cleaner to set this register from the ethernet controller
> based on the phy it is using and keep the MDIO driver purely for MDIO
> bus access.
>
> It is acceptable to overlap the device address ranges, start the
> ethernet controller at 72000 and start the MDIO at 72004, the platform
> bus code automatically nests them.

Ok I did not think this would work, but I kind of prefer that too.
--
Florian
diff mbox

Patch

diff --git a/drivers/net/ethernet/marvell/mvmdio.c b/drivers/net/ethernet/marvell/mvmdio.c
index bdd9047..09e2470 100644
--- a/drivers/net/ethernet/marvell/mvmdio.c
+++ b/drivers/net/ethernet/marvell/mvmdio.c
@@ -32,7 +32,9 @@ 
 #include <linux/delay.h>
 #include <linux/sched.h>
 #include <linux/wait.h>
+#include <linux/marvell_mvmdio.h>
 
+#define MVMDIO_PHY_ADDR			   0x0000
 #define MVMDIO_SMI_REG			   0x0004
 #define MVMDIO_SMI_DATA_SHIFT              0
 #define MVMDIO_SMI_PHY_ADDR_SHIFT          16
@@ -188,6 +190,33 @@  static irqreturn_t orion_mdio_err_irq(int irq, void *dev_id)
 	return IRQ_NONE;
 }
 
+void orion_mdio_phy_addr_set(struct platform_device *pdev,
+				int port_num, int phy_addr)
+{
+	struct orion_mdio_dev *dev =
+		platform_get_drvdata(pdev);
+	int addr_shift = 5 * port_num;
+	u32 data;
+
+	data = readl(dev->regs + MVMDIO_PHY_ADDR);
+	data &= ~(0x1f << addr_shift);
+	data |= (phy_addr & 0x1f) << addr_shift;
+	writel(data, dev->regs + MVMDIO_PHY_ADDR);
+}
+EXPORT_SYMBOL(orion_mdio_phy_addr_set);
+
+int orion_mdio_phy_addr_get(struct platform_device *pdev, int port_num)
+{
+	struct orion_mdio_dev *dev =
+		platform_get_drvdata(pdev);
+	unsigned int data;
+
+	data = readl(dev->regs + MVMDIO_PHY_ADDR);
+
+	return (data >> (5 * port_num)) & 0x1f;
+}
+EXPORT_SYMBOL(orion_mdio_phy_addr_get);
+
 static int orion_mdio_probe(struct platform_device *pdev)
 {
 	struct device_node *np = pdev->dev.of_node;
diff --git a/include/linux/marvell_mvmdio.h b/include/linux/marvell_mvmdio.h
new file mode 100644
index 0000000..c2dfec4
--- /dev/null
+++ b/include/linux/marvell_mvmdio.h
@@ -0,0 +1,10 @@ 
+#ifndef _MARVELL_MVMDIO_H
+#define _MARVELL_MVMDIO_H
+
+#include <linux/platform_device.h>
+
+void orion_mdio_phy_addr_set(struct platform_device *pdev,
+				int port_num, int phy_addr);
+int orion_mdio_phy_addr_get(struct platform_device *pdev, int port_num);
+
+#endif /* _MARVELL_MVMDIO_H */