From: Guo-Fu Tseng Date: Tue, 3 Aug 2010 08:55:51 +0000 (+0800) Subject: Import jme 0.9c source X-Git-Tag: jme-0.9c X-Git-Url: https://bbs.cooldavid.org/git/?p=jme.git;a=commitdiff_plain;h=186fc2591e3b5b6e35e66aef88e4ef7c4d87fd58 Import jme 0.9c source --- diff --git a/jme.c b/jme.c index ac6fc1c..612a058 100644 --- a/jme.c +++ b/jme.c @@ -58,8 +58,9 @@ static int jme_mdio_read(struct net_device *netdev, int phy, int reg) { struct jme_adapter *jme = netdev_priv(netdev); - int i, val; + int i, val, again = (reg == MII_BMSR)?1:0; +read_again: jwrite32(jme, JME_SMI, SMI_OP_REQ | smi_phy_addr(phy) | smi_reg_addr(reg)); @@ -77,6 +78,9 @@ jme_mdio_read(struct net_device *netdev, int phy, int reg) return 0; } + if(again--) + goto read_again; + return ((val & SMI_DATA_MASK) >> SMI_DATA_SHIFT); } @@ -205,7 +209,7 @@ jme_reload_eeprom(struct jme_adapter *jme) jwrite32(jme, JME_SMBCSR, val); mdelay(12); - for (i = JME_SMB_TIMEOUT; i > 0; --i) + for (i = JME_EEPROM_RELOAD_TIMEOUT; i > 0; --i) { mdelay(1); if ((jread32(jme, JME_SMBCSR) & SMBCSR_RELOAD) == 0) @@ -213,12 +217,10 @@ jme_reload_eeprom(struct jme_adapter *jme) } if(i == 0) { - jeprintk(jme->dev->name, "eeprom reload timeout\n"); + jeprintk("jme", "eeprom reload timeout\n"); return -EIO; } } - else - return -EIO; return 0; } @@ -1885,13 +1887,13 @@ jme_set_macaddr(struct net_device *netdev, void *p) spin_lock(&jme->macaddr_lock); memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len); - val = addr->sa_data[3] << 24 | - addr->sa_data[2] << 16 | - addr->sa_data[1] << 8 | - addr->sa_data[0]; + val = (addr->sa_data[3] & 0xff) << 24 | + (addr->sa_data[2] & 0xff) << 16 | + (addr->sa_data[1] & 0xff) << 8 | + (addr->sa_data[0] & 0xff); jwrite32(jme, JME_RXUMA_LO, val); - val = addr->sa_data[5] << 8 | - addr->sa_data[4]; + val = (addr->sa_data[5] & 0xff) << 8 | + (addr->sa_data[4] & 0xff); jwrite32(jme, JME_RXUMA_HI, val); spin_unlock(&jme->macaddr_lock); @@ -2018,7 +2020,7 @@ jme_get_drvinfo(struct net_device *netdev, static int jme_get_regs_len(struct net_device *netdev) { - return 0x400; + return JME_REG_LEN; } static void @@ -2028,7 +2030,16 @@ mmapio_memcpy(struct jme_adapter *jme, __u32 *p, __u32 reg, int len) for(i = 0 ; i < len ; i += 4) p[i >> 2] = jread32(jme, reg + i); +} +static void +mdio_memcpy(struct jme_adapter *jme, __u32 *p, int reg_nr) +{ + int i; + __u16 *p16 = (__u16*)p; + + for(i = 0 ; i < reg_nr ; ++i) + p16[i] = jme_mdio_read(jme->dev, jme->mii_if.phy_id, i); } static void @@ -2037,7 +2048,7 @@ jme_get_regs(struct net_device *netdev, struct ethtool_regs *regs, void *p) struct jme_adapter *jme = netdev_priv(netdev); __u32 *p32 = (__u32*)p; - memset(p, 0, 0x400); + memset(p, 0xFF, JME_REG_LEN); regs->version = 1; mmapio_memcpy(jme, p32, JME_MAC, JME_MAC_LEN); @@ -2051,6 +2062,8 @@ jme_get_regs(struct net_device *netdev, struct ethtool_regs *regs, void *p) p32 += 0x100 >> 2; mmapio_memcpy(jme, p32, JME_RSS, JME_RSS_LEN); + p32 += 0x100 >> 2; + mdio_memcpy(jme, p32, JME_PHY_REG_NR); } static int @@ -2354,6 +2367,124 @@ jme_nway_reset(struct net_device *netdev) return 0; } +static __u8 +jme_smb_read(struct jme_adapter *jme, unsigned int addr) +{ + __u32 val; + int to; + + val = jread32(jme, JME_SMBCSR); + to = JME_SMB_BUSY_TIMEOUT; + while((val & SMBCSR_BUSY) && --to) { + msleep(1); + val = jread32(jme, JME_SMBCSR); + } + if(!to) { + jeprintk(jme->dev->name, "SMB Bus Busy.\n"); + return 0xFF; + } + + jwrite32(jme, JME_SMBINTF, + ((addr << SMBINTF_HWADDR_SHIFT) & SMBINTF_HWADDR) | + SMBINTF_HWRWN_READ | + SMBINTF_HWCMD); + + val = jread32(jme, JME_SMBINTF); + to = JME_SMB_BUSY_TIMEOUT; + while((val & SMBINTF_HWCMD) && --to) { + msleep(1); + val = jread32(jme, JME_SMBINTF); + } + if(!to) { + jeprintk(jme->dev->name, "SMB Bus Busy.\n"); + return 0xFF; + } + + return (val & SMBINTF_HWDATR) >> SMBINTF_HWDATR_SHIFT; +} + +static void +jme_smb_write(struct jme_adapter *jme, unsigned int addr, __u8 data) +{ + __u32 val; + int to; + + val = jread32(jme, JME_SMBCSR); + to = JME_SMB_BUSY_TIMEOUT; + while((val & SMBCSR_BUSY) && --to) { + msleep(1); + val = jread32(jme, JME_SMBCSR); + } + if(!to) { + jeprintk(jme->dev->name, "SMB Bus Busy.\n"); + return; + } + + jwrite32(jme, JME_SMBINTF, + ((data << SMBINTF_HWDATW_SHIFT) & SMBINTF_HWDATW) | + ((addr << SMBINTF_HWADDR_SHIFT) & SMBINTF_HWADDR) | + SMBINTF_HWRWN_WRITE | + SMBINTF_HWCMD); + + val = jread32(jme, JME_SMBINTF); + to = JME_SMB_BUSY_TIMEOUT; + while((val & SMBINTF_HWCMD) && --to) { + msleep(1); + val = jread32(jme, JME_SMBINTF); + } + if(!to) { + jeprintk(jme->dev->name, "SMB Bus Busy.\n"); + return; + } + + mdelay(2); +} + +static int +jme_get_eeprom_len(struct net_device *netdev) +{ + struct jme_adapter *jme = netdev_priv(netdev); + __u32 val; + val = jread32(jme, JME_SMBCSR); + return (val & SMBCSR_EEPROMD)?JME_SMB_LEN:0; +} + +static int +jme_get_eeprom(struct net_device *netdev, + struct ethtool_eeprom *eeprom, u8 *data) +{ + struct jme_adapter *jme = netdev_priv(netdev); + int i, offset = eeprom->offset, len = eeprom->len; + + /* + * ethtool will check boundary for us + */ + eeprom->magic = JME_EEPROM_MAGIC; + for(i = 0 ; i < len ; ++i) + data[i] = jme_smb_read(jme, i + offset); + + return 0; +} + +static int +jme_set_eeprom(struct net_device *netdev, + struct ethtool_eeprom *eeprom, u8 *data) +{ + struct jme_adapter *jme = netdev_priv(netdev); + int i, offset = eeprom->offset, len = eeprom->len; + + if (eeprom->magic != JME_EEPROM_MAGIC) + return -EINVAL; + + /* + * ethtool will check boundary for us + */ + for(i = 0 ; i < len ; ++i) + jme_smb_write(jme, i + offset, data[i]); + + return 0; +} + static const struct ethtool_ops jme_ethtool_ops = { .get_drvinfo = jme_get_drvinfo, .get_regs_len = jme_get_regs_len, @@ -2373,6 +2504,9 @@ static const struct ethtool_ops jme_ethtool_ops = { .set_tso = jme_set_tso, .set_sg = ethtool_op_set_sg, .nway_reset = jme_nway_reset, + .get_eeprom_len = jme_get_eeprom_len, + .get_eeprom = jme_get_eeprom, + .set_eeprom = jme_set_eeprom, }; static int diff --git a/jme.h b/jme.h index 953b1dc..57a270b 100644 --- a/jme.h +++ b/jme.h @@ -24,7 +24,7 @@ #include #define DRV_NAME "jme" -#define DRV_VERSION "0.9b" +#define DRV_VERSION "0.9c" #define PFX DRV_NAME ": " #ifdef DEBUG @@ -447,6 +447,7 @@ enum jme_flags_bits { }; #define WAIT_TASKLET_TIMEOUT 500 /* 500 ms */ #define TX_TIMEOUT (5*HZ) +#define JME_REG_LEN 0x500 #if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,23) __always_inline static struct jme_adapter* @@ -514,6 +515,7 @@ enum jme_iomap_regs { JME_PHY_CS = JME_PHY | 0x28, /* PHY Ctrl and Status Register */ JME_PHY_LINK = JME_PHY | 0x30, /* PHY Link Status Register */ JME_SMBCSR = JME_PHY | 0x40, /* SMB Control and Status */ + JME_SMBINTF = JME_PHY | 0x44, /* SMB Interface */ JME_TMCSR = JME_MISC| 0x00, /* Timer Control/Status Register */ @@ -773,6 +775,7 @@ __always_inline __u32 smi_phy_addr(int x) return (((x) << SMI_PHY_ADDR_SHIFT) & SMI_PHY_ADDR_MASK); } #define JME_PHY_TIMEOUT 1000 /* 1000 msec */ +#define JME_PHY_REG_NR 32 /* * Global Host Control @@ -842,8 +845,33 @@ enum jme_smbcsr_bit_mask { SMBCSR_CNACK = 0x00020000, SMBCSR_RELOAD = 0x00010000, SMBCSR_EEPROMD = 0x00000020, + SMBCSR_INITDONE = 0x00000010, + SMBCSR_BUSY = 0x0000000F, }; -#define JME_SMB_TIMEOUT 10 /* 10 msec */ +enum jme_smbintf_bit_mask { + SMBINTF_HWDATR = 0xFF000000, + SMBINTF_HWDATW = 0x00FF0000, + SMBINTF_HWADDR = 0x0000FF00, + SMBINTF_HWRWN = 0x00000020, + SMBINTF_HWCMD = 0x00000010, + SMBINTF_FASTM = 0x00000008, + SMBINTF_GPIOSCL = 0x00000004, + SMBINTF_GPIOSDA = 0x00000002, + SMBINTF_GPIOEN = 0x00000001, +}; +enum jme_smbintf_vals { + SMBINTF_HWRWN_READ = 0x00000020, + SMBINTF_HWRWN_WRITE = 0x00000000, +}; +enum jme_smbintf_shifts { + SMBINTF_HWDATR_SHIFT = 24, + SMBINTF_HWDATW_SHIFT = 16, + SMBINTF_HWADDR_SHIFT = 8, +}; +#define JME_EEPROM_RELOAD_TIMEOUT 2000 /* 2000 msec */ +#define JME_SMB_BUSY_TIMEOUT 20 /* 20 msec */ +#define JME_SMB_LEN 256 +#define JME_EEPROM_MAGIC 0x250 /* * Timer Control/Status Register