summaryrefslogtreecommitdiffstats
path: root/target/linux/ixp4xx/patches-3.3/207-npe_driver_multiphy_support.patch
blob: d50c545cc157aa4dcf698c7bacf376e058a83d33 (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
151
152
153
154
TODO: take care of additional PHYs through the PHY abstraction layer

--- a/arch/arm/mach-ixp4xx/include/mach/platform.h
+++ b/arch/arm/mach-ixp4xx/include/mach/platform.h
@@ -72,7 +72,7 @@ extern unsigned long ixp4xx_exp_bus_size
 /*
  * Clock Speed Definitions.
  */
-#define IXP4XX_PERIPHERAL_BUS_CLOCK 	(66) /* 66Mhzi APB BUS   */ 
+#define IXP4XX_PERIPHERAL_BUS_CLOCK 	(66) /* 66Mhzi APB BUS   */
 #define IXP4XX_UART_XTAL        	14745600
 
 /*
@@ -95,12 +95,23 @@ struct sys_timer;
 #define IXP4XX_ETH_NPEB		0x10
 #define IXP4XX_ETH_NPEC		0x20
 
+#define IXP4XX_ETH_PHY_MAX_ADDR	32
+
 /* Information about built-in Ethernet MAC interfaces */
 struct eth_plat_info {
 	u8 phy;		/* MII PHY ID, 0 - 31 */
 	u8 rxq;		/* configurable, currently 0 - 31 only */
 	u8 txreadyq;
 	u8 hwaddr[6];
+
+	u32 phy_mask;
+#if 0
+	int speed;
+	int duplex;
+#else
+	int speed_10;
+	int half_duplex;
+#endif
 };
 
 /* Information about built-in HSS (synchronous serial) interfaces */
--- a/drivers/net/ethernet/xscale/ixp4xx_eth.c
+++ b/drivers/net/ethernet/xscale/ixp4xx_eth.c
@@ -594,6 +594,37 @@ static int ixp4xx_phy_connect(struct net
 	struct eth_plat_info *plat = port->plat;
 	char phy_id[MII_BUS_ID_SIZE + 3];
 
+	if (plat->phy == IXP4XX_ETH_PHY_MAX_ADDR) {
+#if 0
+		switch (plat->speed) {
+		case SPEED_10:
+		case SPEED_100:
+			break;
+		default:
+			printk(KERN_ERR "%s: invalid speed (%d)\n",
+					dev->name, plat->speed);
+			return -EINVAL;
+		}
+
+		switch (plat->duplex) {
+		case DUPLEX_HALF:
+		case DUPLEX_FULL:
+			break;
+		default:
+			printk(KERN_ERR "%s: invalid duplex mode (%d)\n",
+					dev->name, plat->duplex);
+			return -EINVAL;
+		}
+		port->speed = plat->speed;
+		port->duplex = plat->duplex;
+#else
+		port->speed = plat->speed_10 ? SPEED_10 : SPEED_100;
+		port->duplex = plat->half_duplex ? DUPLEX_HALF : DUPLEX_FULL;
+#endif
+
+		return 0;
+	}
+
 	snprintf(phy_id, MII_BUS_ID_SIZE + 3, PHY_ID_FMT,
 		mdio_bus->id, plat->phy);
 	port->phydev = phy_connect(dev, phy_id, &ixp4xx_adjust_link, 0,
@@ -616,21 +647,32 @@ static void ixp4xx_phy_disconnect(struct
 {
 	struct port *port = netdev_priv(dev);
 
-	phy_disconnect(port->phydev);
+	if (port->phydev)
+		phy_disconnect(port->phydev);
 }
 
 static void ixp4xx_phy_start(struct net_device *dev)
 {
 	struct port *port = netdev_priv(dev);
 
-	phy_start(port->phydev);
+	if (port->phydev) {
+		phy_start(port->phydev);
+	} else {
+		port->link = 1;
+		ixp4xx_update_link(dev);
+	}
 }
 
 static void ixp4xx_phy_stop(struct net_device *dev)
 {
 	struct port *port = netdev_priv(dev);
 
-	phy_stop(port->phydev);
+	if (port->phydev) {
+		phy_stop(port->phydev);
+	} else {
+		port->link = 0;
+		ixp4xx_update_link(dev);
+	}
 }
 
 static inline void debug_pkt(struct net_device *dev, const char *func,
@@ -1027,6 +1069,9 @@ static int eth_ioctl(struct net_device *
 	if (cpu_is_ixp46x() && cmd == SIOCSHWTSTAMP)
 		return hwtstamp_ioctl(dev, req, cmd);
 
+	if (!port->phydev)
+		return -EOPNOTSUPP;
+
 	return phy_mii_ioctl(port->phydev, req, cmd);
 }
 
@@ -1046,18 +1091,30 @@ static void ixp4xx_get_drvinfo(struct ne
 static int ixp4xx_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
 {
 	struct port *port = netdev_priv(dev);
+
+	if (!port->phydev)
+		return -EOPNOTSUPP;
+
 	return phy_ethtool_gset(port->phydev, cmd);
 }
 
 static int ixp4xx_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
 {
 	struct port *port = netdev_priv(dev);
+
+	if (!port->phydev)
+		return -EOPNOTSUPP;
+
 	return phy_ethtool_sset(port->phydev, cmd);
 }
 
 static int ixp4xx_nway_reset(struct net_device *dev)
 {
 	struct port *port = netdev_priv(dev);
+
+	if (!port->phydev)
+		return -EOPNOTSUPP;
+
 	return phy_start_aneg(port->phydev);
 }