aboutsummaryrefslogtreecommitdiffstats
path: root/recipes-kernel/linux/linux-xlnx/zx3-zynq7/0003-zx3-xilinx_emacps-make-phy-address-configurable.patch
blob: e44f269383f14134459f4f729ce908e805620483 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
From de4fae1849b4d29146a6061f76b763d92cc7e3ef Mon Sep 17 00:00:00 2001
From: David Andrey <david.andrey@netmodule.com>
Date: Tue, 1 Jul 2014 09:33:51 +0200
Subject: [PATCH 3/7] zx3: xilinx_emacps: make phy address configurable

Make the address of the phy configurable so
we can change it at runtime.

Signed-off-by: Stefan Eichenberger <stefan.eichenberger@netmodule.com>

Conflicts:
	drivers/net/ethernet/xilinx/xilinx_emacps.c
---
 drivers/net/ethernet/xilinx/xilinx_emacps.c |   86 +++++++++++++++++++++++++++
 1 file changed, 86 insertions(+)

diff --git a/drivers/net/ethernet/xilinx/xilinx_emacps.c b/drivers/net/ethernet/xilinx/xilinx_emacps.c
index af61503..aba7747 100644
--- a/drivers/net/ethernet/xilinx/xilinx_emacps.c
+++ b/drivers/net/ethernet/xilinx/xilinx_emacps.c
@@ -47,6 +47,7 @@
 #include <linux/ptp_clock_kernel.h>

 /************************** Constant Definitions *****************************/
+#define MAKE_PHY_ADDR_CHANGEABLE

 /* Must be shorter than length of ethtool_drvinfo.driver field to fit */
 #define DRIVER_NAME			"xemacps"
@@ -545,6 +546,9 @@ struct net_local {
	unsigned ip_summed;
	unsigned int enetnum;
	unsigned int lastrxfrmscntr;
+#ifdef MAKE_PHY_ADDR_CHANGEABLE
+	unsigned int phy_number;
+#endif /* MAKE_PHY_ADDR_CHANGEABLE */
 #ifdef CONFIG_XILINX_PS_EMAC_HWTSTAMP
	struct hwtstamp_config hwtstamp_config;
	struct ptp_clock *ptp_clock;
@@ -867,6 +871,44 @@ err_out:
	return rc;
 }

+#ifdef MAKE_PHY_ADDR_CHANGEABLE
+static int xemacps_set_phy(struct net_local *lp, int phy_number)
+{
+	struct device_node *phy_node;
+	int ret;
+
+	phy_node = of_parse_phandle(lp->pdev->dev.of_node,
+			"phy-handle", phy_number);
+	if (phy_node == NULL){
+		return -1;
+	}
+
+	if (lp->phy_dev) {
+		phy_disconnect(lp->phy_dev);
+		lp->phy_dev = NULL;
+	}
+
+	of_node_put(lp->phy_node);
+
+	lp->phy_number = phy_number;
+
+	lp->phy_node = phy_node;
+
+	ret = xemacps_mii_probe(lp->ndev);
+	if (ret == -1) {
+		printk (KERN_ERR "Failed to probe phy!");
+		return -1;
+	}
+
+	return 0;
+}
+
+static int xemacps_get_phy(struct net_local *lp)
+{
+	return lp->phy_number;
+}
+#endif /* MAKE_PHY_ADDR_CHANGEABLE */
+
 /**
  * xemacps_update_hdaddr - Update device's MAC address when configured
  * MAC address is not valid, reconfigure with a good one.
@@ -2782,6 +2824,41 @@ static int xemacps_ioctl(struct net_device *ndev, struct ifreq *rq, int cmd)

 }

+#ifdef MAKE_PHY_ADDR_CHANGEABLE
+static ssize_t
+xemacps_sysfs_show_phy_num(struct device *dev, struct device_attribute *attr,
+				 char *buf)
+{
+	struct net_device *ndev = to_net_dev(dev);
+	struct net_local *lp = netdev_priv(ndev);
+
+	/* External phy numbers are from 1 to *, internal phy numbers from 0 to * */
+	return sprintf (buf,"%d\n", xemacps_get_phy(lp) + 1);
+
+}
+
+static ssize_t
+xemacps_sysfs_store_phy_num(struct device *dev, struct device_attribute *attr,
+				 char *buf, size_t n)
+{
+	struct net_device *ndev = to_net_dev(dev);
+	struct net_local *lp = netdev_priv(ndev);
+	unsigned int phy_number = simple_strtoul(buf, NULL, 10);
+	if (phy_number == 0)
+		return -EINVAL;
+
+	/* External phy numbers are from 1 to *, internal phy numbers from 0 to * */
+	phy_number --;
+	if (xemacps_set_phy(lp, phy_number) != 0)
+		return -EINVAL;
+
+	return n;
+}
+
+static DEVICE_ATTR(phy_num, S_IRUGO | S_IWUSR, xemacps_sysfs_show_phy_num, xemacps_sysfs_store_phy_num);
+
+#endif /* MAKE_PHY_ADDR_CHANGEABLE */
+
 /**
  * xemacps_probe - Platform driver probe
  * @pdev: Pointer to platform device structure
@@ -2909,6 +2986,11 @@ static int xemacps_probe(struct platform_device *pdev)
	lp->txtimeout_handler_wq = create_singlethread_workqueue(DRIVER_NAME);
	INIT_WORK(&lp->txtimeout_reinit, xemacps_reinit_for_txtimeout);

+#ifdef MAKE_PHY_ADDR_CHANGEABLE
+	lp->phy_number = 0;
+	device_create_file(&ndev->dev, &dev_attr_phy_num);
+#endif /* MAKE_PHY_ADDR_CHANGEABLE */
+
	platform_set_drvdata(pdev, ndev);
	pm_runtime_set_active(&pdev->dev);
	pm_runtime_enable(&pdev->dev);
@@ -2952,6 +3034,10 @@ static int xemacps_remove(struct platform_device *pdev)
	if (ndev) {
		lp = netdev_priv(ndev);

+#ifdef MAKE_PHY_ADDR_CHANGEABLE
+		device_remove_file(&ndev->dev, &dev_attr_phy_num);
+#endif /* MAKE_PHY_ADDR_CHANGEABLE */
+
		mdiobus_unregister(lp->mii_bus);
		kfree(lp->mii_bus->irq);
		mdiobus_free(lp->mii_bus);
--
1.7.10.4