aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/mv643xx_eth.c
diff options
context:
space:
mode:
authorLennert Buytenhek <buytenh@wantstofly.org>2008-06-01 20:13:03 -0400
committerLennert Buytenhek <buytenh@wantstofly.org>2008-06-12 02:40:39 -0400
commitbedfe3248efd070acd97d44d8c58cf82d7ebe7c4 (patch)
tree4c5733c282c9c4b57719307cf4d3b298b980339a /drivers/net/mv643xx_eth.c
parent12e4ab79cd828563dc090d2117dc8626b344bc8f (diff)
mv643xx_eth: add PHY-less mode
On some boards, the mv643xx_eth MAC isn't connected to a PHY but directly (via the MII/GMII/RGMII interface) to another MAC-layer device. This patch allows specifying ->phy_addr = -1 to skip all PHY-related initialisation and run-time poking in that case. Signed-off-by: Lennert Buytenhek <buytenh@marvell.com> Acked-by: Dale Farnsworth <dale@farnsworth.org>
Diffstat (limited to 'drivers/net/mv643xx_eth.c')
-rw-r--r--drivers/net/mv643xx_eth.c87
1 files changed, 74 insertions, 13 deletions
diff --git a/drivers/net/mv643xx_eth.c b/drivers/net/mv643xx_eth.c
index 481a2c4ff0cd..a2b958ddf5f0 100644
--- a/drivers/net/mv643xx_eth.c
+++ b/drivers/net/mv643xx_eth.c
@@ -1110,6 +1110,22 @@ static int mv643xx_eth_get_settings(struct net_device *dev, struct ethtool_cmd *
1110 return err; 1110 return err;
1111} 1111}
1112 1112
1113static int mv643xx_eth_get_settings_phyless(struct net_device *dev, struct ethtool_cmd *cmd)
1114{
1115 cmd->supported = SUPPORTED_MII;
1116 cmd->advertising = ADVERTISED_MII;
1117 cmd->speed = SPEED_1000;
1118 cmd->duplex = DUPLEX_FULL;
1119 cmd->port = PORT_MII;
1120 cmd->phy_address = 0;
1121 cmd->transceiver = XCVR_INTERNAL;
1122 cmd->autoneg = AUTONEG_DISABLE;
1123 cmd->maxtxpkt = 1;
1124 cmd->maxrxpkt = 1;
1125
1126 return 0;
1127}
1128
1113static int mv643xx_eth_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) 1129static int mv643xx_eth_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
1114{ 1130{
1115 struct mv643xx_eth_private *mp = netdev_priv(dev); 1131 struct mv643xx_eth_private *mp = netdev_priv(dev);
@@ -1127,6 +1143,11 @@ static int mv643xx_eth_set_settings(struct net_device *dev, struct ethtool_cmd *
1127 return err; 1143 return err;
1128} 1144}
1129 1145
1146static int mv643xx_eth_set_settings_phyless(struct net_device *dev, struct ethtool_cmd *cmd)
1147{
1148 return -EINVAL;
1149}
1150
1130static void mv643xx_eth_get_drvinfo(struct net_device *dev, 1151static void mv643xx_eth_get_drvinfo(struct net_device *dev,
1131 struct ethtool_drvinfo *drvinfo) 1152 struct ethtool_drvinfo *drvinfo)
1132{ 1153{
@@ -1144,6 +1165,11 @@ static int mv643xx_eth_nway_reset(struct net_device *dev)
1144 return mii_nway_restart(&mp->mii); 1165 return mii_nway_restart(&mp->mii);
1145} 1166}
1146 1167
1168static int mv643xx_eth_nway_reset_phyless(struct net_device *dev)
1169{
1170 return -EINVAL;
1171}
1172
1147static u32 mv643xx_eth_get_link(struct net_device *dev) 1173static u32 mv643xx_eth_get_link(struct net_device *dev)
1148{ 1174{
1149 struct mv643xx_eth_private *mp = netdev_priv(dev); 1175 struct mv643xx_eth_private *mp = netdev_priv(dev);
@@ -1151,6 +1177,11 @@ static u32 mv643xx_eth_get_link(struct net_device *dev)
1151 return mii_link_ok(&mp->mii); 1177 return mii_link_ok(&mp->mii);
1152} 1178}
1153 1179
1180static u32 mv643xx_eth_get_link_phyless(struct net_device *dev)
1181{
1182 return 1;
1183}
1184
1154static void mv643xx_eth_get_strings(struct net_device *dev, 1185static void mv643xx_eth_get_strings(struct net_device *dev,
1155 uint32_t stringset, uint8_t *data) 1186 uint32_t stringset, uint8_t *data)
1156{ 1187{
@@ -1210,6 +1241,18 @@ static const struct ethtool_ops mv643xx_eth_ethtool_ops = {
1210 .get_sset_count = mv643xx_eth_get_sset_count, 1241 .get_sset_count = mv643xx_eth_get_sset_count,
1211}; 1242};
1212 1243
1244static const struct ethtool_ops mv643xx_eth_ethtool_ops_phyless = {
1245 .get_settings = mv643xx_eth_get_settings_phyless,
1246 .set_settings = mv643xx_eth_set_settings_phyless,
1247 .get_drvinfo = mv643xx_eth_get_drvinfo,
1248 .nway_reset = mv643xx_eth_nway_reset_phyless,
1249 .get_link = mv643xx_eth_get_link_phyless,
1250 .set_sg = ethtool_op_set_sg,
1251 .get_strings = mv643xx_eth_get_strings,
1252 .get_ethtool_stats = mv643xx_eth_get_ethtool_stats,
1253 .get_sset_count = mv643xx_eth_get_sset_count,
1254};
1255
1213 1256
1214/* address handling *********************************************************/ 1257/* address handling *********************************************************/
1215static void uc_addr_get(struct mv643xx_eth_private *mp, unsigned char *addr) 1258static void uc_addr_get(struct mv643xx_eth_private *mp, unsigned char *addr)
@@ -1656,12 +1699,16 @@ static irqreturn_t mv643xx_eth_irq(int irq, void *dev_id)
1656 } 1699 }
1657 1700
1658 if (int_cause_ext & (INT_EXT_PHY | INT_EXT_LINK)) { 1701 if (int_cause_ext & (INT_EXT_PHY | INT_EXT_LINK)) {
1659 if (mii_link_ok(&mp->mii)) { 1702 if (mp->phy_addr == -1 || mii_link_ok(&mp->mii)) {
1660 struct ethtool_cmd cmd;
1661 int i; 1703 int i;
1662 1704
1663 mii_ethtool_gset(&mp->mii, &cmd); 1705 if (mp->phy_addr != -1) {
1664 update_pscr(mp, cmd.speed, cmd.duplex); 1706 struct ethtool_cmd cmd;
1707
1708 mii_ethtool_gset(&mp->mii, &cmd);
1709 update_pscr(mp, cmd.speed, cmd.duplex);
1710 }
1711
1665 for (i = 0; i < 8; i++) 1712 for (i = 0; i < 8; i++)
1666 if (mp->txq_mask & (1 << i)) 1713 if (mp->txq_mask & (1 << i))
1667 txq_enable(mp->txq + i); 1714 txq_enable(mp->txq + i);
@@ -1751,7 +1798,6 @@ static void phy_reset(struct mv643xx_eth_private *mp)
1751static void port_start(struct mv643xx_eth_private *mp) 1798static void port_start(struct mv643xx_eth_private *mp)
1752{ 1799{
1753 u32 pscr; 1800 u32 pscr;
1754 struct ethtool_cmd ethtool_cmd;
1755 int i; 1801 int i;
1756 1802
1757 /* 1803 /*
@@ -1771,9 +1817,16 @@ static void port_start(struct mv643xx_eth_private *mp)
1771 1817
1772 wrl(mp, SDMA_CONFIG(mp->port_num), PORT_SDMA_CONFIG_DEFAULT_VALUE); 1818 wrl(mp, SDMA_CONFIG(mp->port_num), PORT_SDMA_CONFIG_DEFAULT_VALUE);
1773 1819
1774 mv643xx_eth_get_settings(mp->dev, &ethtool_cmd); 1820 /*
1775 phy_reset(mp); 1821 * Perform PHY reset, if there is a PHY.
1776 mv643xx_eth_set_settings(mp->dev, &ethtool_cmd); 1822 */
1823 if (mp->phy_addr != -1) {
1824 struct ethtool_cmd cmd;
1825
1826 mv643xx_eth_get_settings(mp->dev, &cmd);
1827 phy_reset(mp);
1828 mv643xx_eth_set_settings(mp->dev, &cmd);
1829 }
1777 1830
1778 /* 1831 /*
1779 * Configure TX path and queues. 1832 * Configure TX path and queues.
@@ -1990,7 +2043,10 @@ static int mv643xx_eth_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
1990{ 2043{
1991 struct mv643xx_eth_private *mp = netdev_priv(dev); 2044 struct mv643xx_eth_private *mp = netdev_priv(dev);
1992 2045
1993 return generic_mii_ioctl(&mp->mii, if_mii(ifr), cmd, NULL); 2046 if (mp->phy_addr != -1)
2047 return generic_mii_ioctl(&mp->mii, if_mii(ifr), cmd, NULL);
2048
2049 return -EOPNOTSUPP;
1994} 2050}
1995 2051
1996static int mv643xx_eth_change_mtu(struct net_device *dev, int new_mtu) 2052static int mv643xx_eth_change_mtu(struct net_device *dev, int new_mtu)
@@ -2387,10 +2443,15 @@ static int mv643xx_eth_probe(struct platform_device *pdev)
2387 mib_counters_clear(mp); 2443 mib_counters_clear(mp);
2388 INIT_WORK(&mp->tx_timeout_task, tx_timeout_task); 2444 INIT_WORK(&mp->tx_timeout_task, tx_timeout_task);
2389 2445
2390 err = phy_init(mp, pd); 2446 if (mp->phy_addr != -1) {
2391 if (err) 2447 err = phy_init(mp, pd);
2392 goto out; 2448 if (err)
2393 SET_ETHTOOL_OPS(dev, &mv643xx_eth_ethtool_ops); 2449 goto out;
2450
2451 SET_ETHTOOL_OPS(dev, &mv643xx_eth_ethtool_ops);
2452 } else {
2453 SET_ETHTOOL_OPS(dev, &mv643xx_eth_ethtool_ops_phyless);
2454 }
2394 2455
2395 2456
2396 res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); 2457 res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);