aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/skge.c
diff options
context:
space:
mode:
authorStephen Hemminger <shemminger@osdl.org>2005-11-08 13:33:42 -0500
committerJeff Garzik <jgarzik@pobox.com>2005-11-08 23:58:08 -0500
commit2cd8e5d36584653c62a6fdf0e7d9fbde5022b5d6 (patch)
tree6c3298644228adf71d26a34e8f0028d47c38973b /drivers/net/skge.c
parent7e86306113ca9e418e49ff1c7c0984f8ffe8cf61 (diff)
[PATCH] skge: add mii ioctl support
Basic MII ioctl support for skge driver. Signed-off-by: Stephen Hemminger <shemminger@osdl.org> Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
Diffstat (limited to 'drivers/net/skge.c')
-rw-r--r--drivers/net/skge.c172
1 files changed, 114 insertions, 58 deletions
diff --git a/drivers/net/skge.c b/drivers/net/skge.c
index f411c5c80410..a1cfead5827b 100644
--- a/drivers/net/skge.c
+++ b/drivers/net/skge.c
@@ -37,6 +37,7 @@
37#include <linux/delay.h> 37#include <linux/delay.h>
38#include <linux/crc32.h> 38#include <linux/crc32.h>
39#include <linux/dma-mapping.h> 39#include <linux/dma-mapping.h>
40#include <linux/mii.h>
40#include <asm/irq.h> 41#include <asm/irq.h>
41 42
42#include "skge.h" 43#include "skge.h"
@@ -88,8 +89,8 @@ MODULE_DEVICE_TABLE(pci, skge_id_table);
88static int skge_up(struct net_device *dev); 89static int skge_up(struct net_device *dev);
89static int skge_down(struct net_device *dev); 90static int skge_down(struct net_device *dev);
90static void skge_tx_clean(struct skge_port *skge); 91static void skge_tx_clean(struct skge_port *skge);
91static void xm_phy_write(struct skge_hw *hw, int port, u16 reg, u16 val); 92static int xm_phy_write(struct skge_hw *hw, int port, u16 reg, u16 val);
92static void gm_phy_write(struct skge_hw *hw, int port, u16 reg, u16 val); 93static int gm_phy_write(struct skge_hw *hw, int port, u16 reg, u16 val);
93static void genesis_get_stats(struct skge_port *skge, u64 *data); 94static void genesis_get_stats(struct skge_port *skge, u64 *data);
94static void yukon_get_stats(struct skge_port *skge, u64 *data); 95static void yukon_get_stats(struct skge_port *skge, u64 *data);
95static void yukon_init(struct skge_hw *hw, int port); 96static void yukon_init(struct skge_hw *hw, int port);
@@ -883,32 +884,37 @@ static void skge_link_down(struct skge_port *skge)
883 printk(KERN_INFO PFX "%s: Link is down.\n", skge->netdev->name); 884 printk(KERN_INFO PFX "%s: Link is down.\n", skge->netdev->name);
884} 885}
885 886
886static u16 xm_phy_read(struct skge_hw *hw, int port, u16 reg) 887static int __xm_phy_read(struct skge_hw *hw, int port, u16 reg, u16 *val)
887{ 888{
888 int i; 889 int i;
889 u16 v;
890 890
891 xm_write16(hw, port, XM_PHY_ADDR, reg | hw->phy_addr); 891 xm_write16(hw, port, XM_PHY_ADDR, reg | hw->phy_addr);
892 v = xm_read16(hw, port, XM_PHY_DATA); 892 xm_read16(hw, port, XM_PHY_DATA);
893 893
894 /* Need to wait for external PHY */ 894 /* Need to wait for external PHY */
895 for (i = 0; i < PHY_RETRIES; i++) { 895 for (i = 0; i < PHY_RETRIES; i++) {
896 udelay(1); 896 udelay(1);
897 if (xm_read16(hw, port, XM_MMU_CMD) 897 if (xm_read16(hw, port, XM_MMU_CMD) & XM_MMU_PHY_RDY)
898 & XM_MMU_PHY_RDY)
899 goto ready; 898 goto ready;
900 } 899 }
901 900
902 printk(KERN_WARNING PFX "%s: phy read timed out\n", 901 return -ETIMEDOUT;
903 hw->dev[port]->name);
904 return 0;
905 ready: 902 ready:
906 v = xm_read16(hw, port, XM_PHY_DATA); 903 *val = xm_read16(hw, port, XM_PHY_DATA);
907 904
905 return 0;
906}
907
908static u16 xm_phy_read(struct skge_hw *hw, int port, u16 reg)
909{
910 u16 v = 0;
911 if (__xm_phy_read(hw, port, reg, &v))
912 printk(KERN_WARNING PFX "%s: phy read timed out\n",
913 hw->dev[port]->name);
908 return v; 914 return v;
909} 915}
910 916
911static void xm_phy_write(struct skge_hw *hw, int port, u16 reg, u16 val) 917static int xm_phy_write(struct skge_hw *hw, int port, u16 reg, u16 val)
912{ 918{
913 int i; 919 int i;
914 920
@@ -918,19 +924,11 @@ static void xm_phy_write(struct skge_hw *hw, int port, u16 reg, u16 val)
918 goto ready; 924 goto ready;
919 udelay(1); 925 udelay(1);
920 } 926 }
921 printk(KERN_WARNING PFX "%s: phy write failed to come ready\n", 927 return -EIO;
922 hw->dev[port]->name);
923
924 928
925 ready: 929 ready:
926 xm_write16(hw, port, XM_PHY_DATA, val); 930 xm_write16(hw, port, XM_PHY_DATA, val);
927 for (i = 0; i < PHY_RETRIES; i++) { 931 return 0;
928 udelay(1);
929 if (!(xm_read16(hw, port, XM_MMU_CMD) & XM_MMU_PHY_BUSY))
930 return;
931 }
932 printk(KERN_WARNING PFX "%s: phy write timed out\n",
933 hw->dev[port]->name);
934} 932}
935 933
936static void genesis_init(struct skge_hw *hw) 934static void genesis_init(struct skge_hw *hw)
@@ -1400,42 +1398,6 @@ static void genesis_mac_intr(struct skge_hw *hw, int port)
1400 } 1398 }
1401} 1399}
1402 1400
1403static void gm_phy_write(struct skge_hw *hw, int port, u16 reg, u16 val)
1404{
1405 int i;
1406
1407 gma_write16(hw, port, GM_SMI_DATA, val);
1408 gma_write16(hw, port, GM_SMI_CTRL,
1409 GM_SMI_CT_PHY_AD(hw->phy_addr) | GM_SMI_CT_REG_AD(reg));
1410 for (i = 0; i < PHY_RETRIES; i++) {
1411 udelay(1);
1412
1413 if (!(gma_read16(hw, port, GM_SMI_CTRL) & GM_SMI_CT_BUSY))
1414 break;
1415 }
1416}
1417
1418static u16 gm_phy_read(struct skge_hw *hw, int port, u16 reg)
1419{
1420 int i;
1421
1422 gma_write16(hw, port, GM_SMI_CTRL,
1423 GM_SMI_CT_PHY_AD(hw->phy_addr)
1424 | GM_SMI_CT_REG_AD(reg) | GM_SMI_CT_OP_RD);
1425
1426 for (i = 0; i < PHY_RETRIES; i++) {
1427 udelay(1);
1428 if (gma_read16(hw, port, GM_SMI_CTRL) & GM_SMI_CT_RD_VAL)
1429 goto ready;
1430 }
1431
1432 printk(KERN_WARNING PFX "%s: phy read timeout\n",
1433 hw->dev[port]->name);
1434 return 0;
1435 ready:
1436 return gma_read16(hw, port, GM_SMI_DATA);
1437}
1438
1439static void genesis_link_up(struct skge_port *skge) 1401static void genesis_link_up(struct skge_port *skge)
1440{ 1402{
1441 struct skge_hw *hw = skge->hw; 1403 struct skge_hw *hw = skge->hw;
@@ -1549,6 +1511,54 @@ static inline void bcom_phy_intr(struct skge_port *skge)
1549 1511
1550} 1512}
1551 1513
1514static int gm_phy_write(struct skge_hw *hw, int port, u16 reg, u16 val)
1515{
1516 int i;
1517
1518 gma_write16(hw, port, GM_SMI_DATA, val);
1519 gma_write16(hw, port, GM_SMI_CTRL,
1520 GM_SMI_CT_PHY_AD(hw->phy_addr) | GM_SMI_CT_REG_AD(reg));
1521 for (i = 0; i < PHY_RETRIES; i++) {
1522 udelay(1);
1523
1524 if (!(gma_read16(hw, port, GM_SMI_CTRL) & GM_SMI_CT_BUSY))
1525 return 0;
1526 }
1527
1528 printk(KERN_WARNING PFX "%s: phy write timeout\n",
1529 hw->dev[port]->name);
1530 return -EIO;
1531}
1532
1533static int __gm_phy_read(struct skge_hw *hw, int port, u16 reg, u16 *val)
1534{
1535 int i;
1536
1537 gma_write16(hw, port, GM_SMI_CTRL,
1538 GM_SMI_CT_PHY_AD(hw->phy_addr)
1539 | GM_SMI_CT_REG_AD(reg) | GM_SMI_CT_OP_RD);
1540
1541 for (i = 0; i < PHY_RETRIES; i++) {
1542 udelay(1);
1543 if (gma_read16(hw, port, GM_SMI_CTRL) & GM_SMI_CT_RD_VAL)
1544 goto ready;
1545 }
1546
1547 return -ETIMEDOUT;
1548 ready:
1549 *val = gma_read16(hw, port, GM_SMI_DATA);
1550 return 0;
1551}
1552
1553static u16 gm_phy_read(struct skge_hw *hw, int port, u16 reg)
1554{
1555 u16 v = 0;
1556 if (__gm_phy_read(hw, port, reg, &v))
1557 printk(KERN_WARNING PFX "%s: phy read timeout\n",
1558 hw->dev[port]->name);
1559 return v;
1560}
1561
1552/* Marvell Phy Initailization */ 1562/* Marvell Phy Initailization */
1553static void yukon_init(struct skge_hw *hw, int port) 1563static void yukon_init(struct skge_hw *hw, int port)
1554{ 1564{
@@ -1997,6 +2007,51 @@ static void yukon_phy_intr(struct skge_port *skge)
1997 /* XXX restart autonegotiation? */ 2007 /* XXX restart autonegotiation? */
1998} 2008}
1999 2009
2010/* Basic MII support */
2011static int skge_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
2012{
2013 struct mii_ioctl_data *data = if_mii(ifr);
2014 struct skge_port *skge = netdev_priv(dev);
2015 struct skge_hw *hw = skge->hw;
2016 int err = -EOPNOTSUPP;
2017
2018 if (!netif_running(dev))
2019 return -ENODEV; /* Phy still in reset */
2020
2021 switch(cmd) {
2022 case SIOCGMIIPHY:
2023 data->phy_id = hw->phy_addr;
2024
2025 /* fallthru */
2026 case SIOCGMIIREG: {
2027 u16 val = 0;
2028 spin_lock_bh(&hw->phy_lock);
2029 if (hw->chip_id == CHIP_ID_GENESIS)
2030 err = __xm_phy_read(hw, skge->port, data->reg_num & 0x1f, &val);
2031 else
2032 err = __gm_phy_read(hw, skge->port, data->reg_num & 0x1f, &val);
2033 spin_unlock_bh(&hw->phy_lock);
2034 data->val_out = val;
2035 break;
2036 }
2037
2038 case SIOCSMIIREG:
2039 if (!capable(CAP_NET_ADMIN))
2040 return -EPERM;
2041
2042 spin_lock_bh(&hw->phy_lock);
2043 if (hw->chip_id == CHIP_ID_GENESIS)
2044 err = xm_phy_write(hw, skge->port, data->reg_num & 0x1f,
2045 data->val_in);
2046 else
2047 err = gm_phy_write(hw, skge->port, data->reg_num & 0x1f,
2048 data->val_in);
2049 spin_unlock_bh(&hw->phy_lock);
2050 break;
2051 }
2052 return err;
2053}
2054
2000static void skge_ramset(struct skge_hw *hw, u16 q, u32 start, size_t len) 2055static void skge_ramset(struct skge_hw *hw, u16 q, u32 start, size_t len)
2001{ 2056{
2002 u32 end; 2057 u32 end;
@@ -3058,6 +3113,7 @@ static struct net_device *skge_devinit(struct skge_hw *hw, int port,
3058 SET_NETDEV_DEV(dev, &hw->pdev->dev); 3113 SET_NETDEV_DEV(dev, &hw->pdev->dev);
3059 dev->open = skge_up; 3114 dev->open = skge_up;
3060 dev->stop = skge_down; 3115 dev->stop = skge_down;
3116 dev->do_ioctl = skge_ioctl;
3061 dev->hard_start_xmit = skge_xmit_frame; 3117 dev->hard_start_xmit = skge_xmit_frame;
3062 dev->get_stats = skge_get_stats; 3118 dev->get_stats = skge_get_stats;
3063 if (hw->chip_id == CHIP_ID_GENESIS) 3119 if (hw->chip_id == CHIP_ID_GENESIS)