mirror of
https://github.com/FEX-Emu/linux.git
synced 2024-12-16 22:10:24 +00:00
smc91x: enable ethtool EEPROM interface
Signed-off-by: Vernon Sauder <vsauder@inhand.com> Acked-by: Nicolas Pitre <nico@cam.org> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
31e2b7bd21
commit
357fe2c6d2
@ -1643,6 +1643,117 @@ static void smc_ethtool_setmsglevel(struct net_device *dev, u32 level)
|
||||
lp->msg_enable = level;
|
||||
}
|
||||
|
||||
static int smc_write_eeprom_word(struct net_device *dev, u16 addr, u16 word)
|
||||
{
|
||||
u16 ctl;
|
||||
struct smc_local *lp = netdev_priv(dev);
|
||||
void __iomem *ioaddr = lp->base;
|
||||
|
||||
spin_lock_irq(&lp->lock);
|
||||
/* load word into GP register */
|
||||
SMC_SELECT_BANK(lp, 1);
|
||||
SMC_SET_GP(lp, word);
|
||||
/* set the address to put the data in EEPROM */
|
||||
SMC_SELECT_BANK(lp, 2);
|
||||
SMC_SET_PTR(lp, addr);
|
||||
/* tell it to write */
|
||||
SMC_SELECT_BANK(lp, 1);
|
||||
ctl = SMC_GET_CTL(lp);
|
||||
SMC_SET_CTL(lp, ctl | (CTL_EEPROM_SELECT | CTL_STORE));
|
||||
/* wait for it to finish */
|
||||
do {
|
||||
udelay(1);
|
||||
} while (SMC_GET_CTL(lp) & CTL_STORE);
|
||||
/* clean up */
|
||||
SMC_SET_CTL(lp, ctl);
|
||||
SMC_SELECT_BANK(lp, 2);
|
||||
spin_unlock_irq(&lp->lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int smc_read_eeprom_word(struct net_device *dev, u16 addr, u16 *word)
|
||||
{
|
||||
u16 ctl;
|
||||
struct smc_local *lp = netdev_priv(dev);
|
||||
void __iomem *ioaddr = lp->base;
|
||||
|
||||
spin_lock_irq(&lp->lock);
|
||||
/* set the EEPROM address to get the data from */
|
||||
SMC_SELECT_BANK(lp, 2);
|
||||
SMC_SET_PTR(lp, addr | PTR_READ);
|
||||
/* tell it to load */
|
||||
SMC_SELECT_BANK(lp, 1);
|
||||
SMC_SET_GP(lp, 0xffff); /* init to known */
|
||||
ctl = SMC_GET_CTL(lp);
|
||||
SMC_SET_CTL(lp, ctl | (CTL_EEPROM_SELECT | CTL_RELOAD));
|
||||
/* wait for it to finish */
|
||||
do {
|
||||
udelay(1);
|
||||
} while (SMC_GET_CTL(lp) & CTL_RELOAD);
|
||||
/* read word from GP register */
|
||||
*word = SMC_GET_GP(lp);
|
||||
/* clean up */
|
||||
SMC_SET_CTL(lp, ctl);
|
||||
SMC_SELECT_BANK(lp, 2);
|
||||
spin_unlock_irq(&lp->lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int smc_ethtool_geteeprom_len(struct net_device *dev)
|
||||
{
|
||||
return 0x23 * 2;
|
||||
}
|
||||
|
||||
static int smc_ethtool_geteeprom(struct net_device *dev,
|
||||
struct ethtool_eeprom *eeprom, u8 *data)
|
||||
{
|
||||
int i;
|
||||
int imax;
|
||||
|
||||
DBG(1, "Reading %d bytes at %d(0x%x)\n",
|
||||
eeprom->len, eeprom->offset, eeprom->offset);
|
||||
imax = smc_ethtool_geteeprom_len(dev);
|
||||
for (i = 0; i < eeprom->len; i += 2) {
|
||||
int ret;
|
||||
u16 wbuf;
|
||||
int offset = i + eeprom->offset;
|
||||
if (offset > imax)
|
||||
break;
|
||||
ret = smc_read_eeprom_word(dev, offset >> 1, &wbuf);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
DBG(2, "Read 0x%x from 0x%x\n", wbuf, offset >> 1);
|
||||
data[i] = (wbuf >> 8) & 0xff;
|
||||
data[i+1] = wbuf & 0xff;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int smc_ethtool_seteeprom(struct net_device *dev,
|
||||
struct ethtool_eeprom *eeprom, u8 *data)
|
||||
{
|
||||
int i;
|
||||
int imax;
|
||||
|
||||
DBG(1, "Writing %d bytes to %d(0x%x)\n",
|
||||
eeprom->len, eeprom->offset, eeprom->offset);
|
||||
imax = smc_ethtool_geteeprom_len(dev);
|
||||
for (i = 0; i < eeprom->len; i += 2) {
|
||||
int ret;
|
||||
u16 wbuf;
|
||||
int offset = i + eeprom->offset;
|
||||
if (offset > imax)
|
||||
break;
|
||||
wbuf = (data[i] << 8) | data[i + 1];
|
||||
DBG(2, "Writing 0x%x to 0x%x\n", wbuf, offset >> 1);
|
||||
ret = smc_write_eeprom_word(dev, offset >> 1, wbuf);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static const struct ethtool_ops smc_ethtool_ops = {
|
||||
.get_settings = smc_ethtool_getsettings,
|
||||
.set_settings = smc_ethtool_setsettings,
|
||||
@ -1652,8 +1763,9 @@ static const struct ethtool_ops smc_ethtool_ops = {
|
||||
.set_msglevel = smc_ethtool_setmsglevel,
|
||||
.nway_reset = smc_ethtool_nwayreset,
|
||||
.get_link = ethtool_op_get_link,
|
||||
// .get_eeprom = smc_ethtool_geteeprom,
|
||||
// .set_eeprom = smc_ethtool_seteeprom,
|
||||
.get_eeprom_len = smc_ethtool_geteeprom_len,
|
||||
.get_eeprom = smc_ethtool_geteeprom,
|
||||
.set_eeprom = smc_ethtool_seteeprom,
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -1141,6 +1141,16 @@ static const char * chip_ids[ 16 ] = {
|
||||
|
||||
#define SMC_GET_MII(lp) SMC_inw(ioaddr, MII_REG(lp))
|
||||
|
||||
#define SMC_GET_GP(lp) SMC_inw(ioaddr, GP_REG(lp))
|
||||
|
||||
#define SMC_SET_GP(lp, x) \
|
||||
do { \
|
||||
if (SMC_MUST_ALIGN_WRITE(lp)) \
|
||||
SMC_outl((x)<<16, ioaddr, SMC_REG(lp, 8, 1)); \
|
||||
else \
|
||||
SMC_outw(x, ioaddr, GP_REG(lp)); \
|
||||
} while (0)
|
||||
|
||||
#define SMC_SET_MII(lp, x) SMC_outw(x, ioaddr, MII_REG(lp))
|
||||
|
||||
#define SMC_GET_MIR(lp) SMC_inw(ioaddr, MIR_REG(lp))
|
||||
|
Loading…
Reference in New Issue
Block a user