/* Caller must hold etsects->lock. */ static u64 tmr_cnt_read(struct etsects *etsects) { u64 ns; u32 lo, hi; lo = gfar_read(&etsects->regs->tmr_cnt_l); hi = gfar_read(&etsects->regs->tmr_cnt_h); ns = ((u64) hi) << 32; ns |= lo; return ns; }
static ssize_t gfar_set_fifo_threshold(struct class_device *cdev, const char *buf, size_t count) { struct net_device *dev = to_net_dev(cdev); struct gfar_private *priv = netdev_priv(dev); unsigned int length = simple_strtoul(buf, NULL, 0); u32 temp; unsigned long flags; if (length > GFAR_MAX_FIFO_THRESHOLD) return count; spin_lock_irqsave(&priv->txlock, flags); priv->fifo_threshold = length; temp = gfar_read(&priv->regs->fifo_tx_thr); temp &= ~FIFO_TX_THR_MASK; temp |= length; gfar_write(&priv->regs->fifo_tx_thr, temp); spin_unlock_irqrestore(&priv->txlock, flags); return count; }
static ssize_t gfar_set_bd_stash(struct class_device *cdev, const char *buf, size_t count) { struct net_device *dev = to_net_dev(cdev); struct gfar_private *priv = netdev_priv(dev); int new_setting = 0; u32 temp; unsigned long flags; /* Find out the new setting */ if (!strncmp("on", buf, count-1) || !strncmp("1", buf, count-1)) new_setting = 1; else if (!strncmp("off", buf, count-1) || !strncmp("0", buf, count-1)) new_setting = 0; else return count; spin_lock_irqsave(&priv->rxlock, flags); /* Set the new stashing value */ priv->bd_stash_en = new_setting; temp = gfar_read(&priv->regs->attr); if (new_setting) temp |= ATTR_BDSTASH; else temp &= ~(ATTR_BDSTASH); gfar_write(&priv->regs->attr, temp); spin_unlock_irqrestore(&priv->rxlock, flags); return count; }
static ssize_t gfar_set_rx_stash_index(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct gfar_private *priv = netdev_priv(to_net_dev(dev)); struct gfar __iomem *regs = priv->gfargrp[0].regs; unsigned short index = simple_strtoul(buf, NULL, 0); u32 temp; unsigned long flags; if (!(priv->device_flags & FSL_GIANFAR_DEV_HAS_BUF_STASHING)) return count; local_irq_save(flags); lock_rx_qs(priv); if (index > priv->rx_stash_size) goto out; if (index == priv->rx_stash_index) goto out; priv->rx_stash_index = index; temp = gfar_read(®s->attreli); temp &= ~ATTRELI_EI_MASK; temp |= ATTRELI_EI(index); gfar_write(®s->attreli, temp); out: unlock_rx_qs(priv); local_irq_restore(flags); return count; }
static ssize_t gfar_set_fifo_starve_off(struct class_device *cdev, const char *buf, size_t count) { struct net_device *dev = to_net_dev(cdev); struct gfar_private *priv = netdev_priv(dev); unsigned int num = simple_strtoul(buf, NULL, 0); u32 temp; unsigned long flags; if (num > GFAR_MAX_FIFO_STARVE_OFF) return count; spin_lock_irqsave(&priv->txlock, flags); priv->fifo_starve_off = num; temp = gfar_read(&priv->regs->fifo_tx_starve_shutoff); temp &= ~FIFO_TX_STARVE_OFF_MASK; temp |= num; gfar_write(&priv->regs->fifo_tx_starve_shutoff, temp); spin_unlock_irqrestore(&priv->txlock, flags); return count; }
static ssize_t gfar_set_fifo_threshold(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct gfar_private *priv = netdev_priv(to_net_dev(dev)); struct gfar __iomem *regs = priv->gfargrp[0].regs; unsigned int length = simple_strtoul(buf, NULL, 0); u32 temp; unsigned long flags; if (length > GFAR_MAX_FIFO_THRESHOLD) return count; local_irq_save(flags); lock_tx_qs(priv); priv->fifo_threshold = length; temp = gfar_read(®s->fifo_tx_thr); temp &= ~FIFO_TX_THR_MASK; temp |= length; gfar_write(®s->fifo_tx_thr, temp); unlock_tx_qs(priv); local_irq_restore(flags); return count; }
static ssize_t gfar_set_fifo_starve_off(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct gfar_private *priv = netdev_priv(to_net_dev(dev)); struct gfar __iomem *regs = priv->gfargrp[0].regs; unsigned int num = simple_strtoul(buf, NULL, 0); u32 temp; unsigned long flags; if (num > GFAR_MAX_FIFO_STARVE_OFF) return count; local_irq_save(flags); lock_tx_qs(priv); priv->fifo_starve_off = num; temp = gfar_read(®s->fifo_tx_starve_shutoff); temp &= ~FIFO_TX_STARVE_OFF_MASK; temp |= num; gfar_write(®s->fifo_tx_starve_shutoff, temp); unlock_tx_qs(priv); local_irq_restore(flags); return count; }
static ssize_t gfar_set_rx_stash_index(struct class_device *cdev, const char *buf, size_t count) { struct net_device *dev = to_net_dev(cdev); struct gfar_private *priv = netdev_priv(dev); unsigned short index = simple_strtoul(buf, NULL, 0); u32 temp; unsigned long flags; spin_lock_irqsave(&priv->rxlock, flags); if (index > priv->rx_stash_size) return count; if (index == priv->rx_stash_index) return count; priv->rx_stash_index = index; temp = gfar_read(&priv->regs->attreli); temp &= ~ATTRELI_EI_MASK; temp |= ATTRELI_EI(index); gfar_write(&priv->regs->attreli, flags); spin_unlock_irqrestore(&priv->rxlock, flags); return count; }
static ssize_t gfar_set_fifo_starve(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct gfar_private *priv = netdev_priv(to_net_dev(dev)); unsigned int num = simple_strtoul(buf, NULL, 0); u32 temp; unsigned long flags; if (num > GFAR_MAX_FIFO_STARVE) return count; spin_lock_irqsave(&priv->txlock, flags); priv->fifo_starve = num; temp = gfar_read(&priv->regs->fifo_tx_starve); temp &= ~FIFO_TX_STARVE_MASK; temp |= num; gfar_write(&priv->regs->fifo_tx_starve, temp); spin_unlock_irqrestore(&priv->txlock, flags); return count; }
/* Reset the MIIM registers, and wait for the bus to free */ int gfar_mdio_reset(struct mii_bus *bus) { struct gfar_mii __iomem *regs = (void __iomem *)bus->priv; unsigned int timeout = PHY_INIT_TIMEOUT; spin_lock_bh(&bus->mdio_lock); /* Reset the management interface */ gfar_write(®s->miimcfg, MIIMCFG_RESET); /* Setup the MII Mgmt clock speed */ gfar_write(®s->miimcfg, MIIMCFG_INIT_VALUE); /* Wait until the bus is free */ while ((gfar_read(®s->miimind) & MIIMIND_BUSY) && timeout--) cpu_relax(); spin_unlock_bh(&bus->mdio_lock); if(timeout <= 0) { printk(KERN_ERR "%s: The MII Bus is stuck!\n", bus->name); return -EBUSY; } return 0; }
static ssize_t gfar_set_rx_stash_size(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct gfar_private *priv = netdev_priv(to_net_dev(dev)); struct gfar __iomem *regs = priv->gfargrp[0].regs; unsigned int length = simple_strtoul(buf, NULL, 0); u32 temp; unsigned long flags; if (!(priv->device_flags & FSL_GIANFAR_DEV_HAS_BUF_STASHING)) return count; local_irq_save(flags); lock_rx_qs(priv); if (length > priv->rx_buffer_size) goto out; if (length == priv->rx_stash_size) goto out; priv->rx_stash_size = length; temp = gfar_read(®s->attreli); temp &= ~ATTRELI_EL_MASK; temp |= ATTRELI_EL(length); gfar_write(®s->attreli, temp); /* Turn stashing on/off as appropriate */ temp = gfar_read(®s->attr); if (length) temp |= ATTR_BUFSTASH; else temp &= ~(ATTR_BUFSTASH); gfar_write(®s->attr, temp); out: unlock_rx_qs(priv); local_irq_restore(flags); return count; }
/* Return a dump of the GFAR register space */ static void gfar_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *regbuf) { int i; struct gfar_private *priv = netdev_priv(dev); u32 __iomem *theregs = (u32 __iomem *) priv->regs; u32 *buf = (u32 *) regbuf; for (i = 0; i < sizeof (struct gfar) / sizeof (u32); i++) buf[i] = gfar_read(&theregs[i]); }
/* Read the bus for PHY at addr mii_id, register regnum, and * return the value. Clears miimcom first. All PHY * Operation done on the bus attached to the local interface, * which may be different from the generic mdio bus * This is helpful in programming interfaces like * the TBI which, inturn, control interfaces like onchip SERDES * and are always tied to the local mdio pins, which may not be the * same as system mdio bus, used for controlling the external PHYs, for example. */ int gfar_local_mdio_read(struct gfar_mii *regs, int mii_id, int regnum) { u16 value; /* Set the PHY address and the register address we want to read */ gfar_write(®s->miimadd, (mii_id << 8) | regnum); /* Clear miimcom, and then initiate a read */ gfar_write(®s->miimcom, 0); gfar_write(®s->miimcom, MII_READ_COMMAND); /* Wait for the transaction to finish */ while (gfar_read(®s->miimind) & (MIIMIND_NOTVALID | MIIMIND_BUSY)) cpu_relax(); /* Grab the value of the register from miimstat */ value = gfar_read(®s->miimstat); return value; }
static ssize_t gfar_set_rx_stash_size(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct gfar_private *priv = netdev_priv(to_net_dev(dev)); unsigned int length = simple_strtoul(buf, NULL, 0); u32 temp; unsigned long flags; if (!(priv->device_flags & FSL_GIANFAR_DEV_HAS_BUF_STASHING)) return count; spin_lock_irqsave(&priv->rxlock, flags); if (length > priv->rx_buffer_size) goto out; if (length == priv->rx_stash_size) goto out; priv->rx_stash_size = length; temp = gfar_read(&priv->regs->attreli); temp &= ~ATTRELI_EL_MASK; temp |= ATTRELI_EL(length); gfar_write(&priv->regs->attreli, temp); temp = gfar_read(&priv->regs->attr); if (length) temp |= ATTR_BUFSTASH; else temp &= ~(ATTR_BUFSTASH); gfar_write(&priv->regs->attr, temp); out: spin_unlock_irqrestore(&priv->rxlock, flags); return count; }
/* configuration has to be done through the TSEC1 MIIM regs */ int read_phy_reg(struct net_device *dev, int mii_id, int regnum) { struct gfar_private *priv = netdev_priv(dev); struct gfar *regbase = priv->phyregs; u16 value; /* Set the PHY address and the register address we want to read */ gfar_write(®base->miimadd, (mii_id << 8) | regnum); /* Clear miimcom, and then initiate a read */ gfar_write(®base->miimcom, 0); gfar_write(®base->miimcom, MII_READ_COMMAND); /* Wait for the transaction to finish */ while (gfar_read(®base->miimind) & (MIIMIND_NOTVALID | MIIMIND_BUSY)) cpu_relax(); /* Grab the value of the register from miimstat */ value = gfar_read(®base->miimstat); return value; }
/* Write value to the PHY at mii_id at register regnum, * on the bus attached to the local interface, which may be different from the * generic mdio bus (tied to a single interface), waiting until the write is * done before returning. This is helpful in programming interfaces like * the TBI which control interfaces like onchip SERDES and are always tied to * the local mdio pins, which may not be the same as system mdio bus, used for * controlling the external PHYs, for example. */ int gfar_local_mdio_write(struct gfar_mii *regs, int mii_id, int regnum, u16 value) { /* Set the PHY address and the register address we want to write */ gfar_write(®s->miimadd, (mii_id << 8) | regnum); /* Write out the value we want */ gfar_write(®s->miimcon, value); /* Wait for the transaction to finish */ while (gfar_read(®s->miimind) & MIIMIND_BUSY) cpu_relax(); return 0; }
static ssize_t gfar_set_rx_stash_size(struct class_device *cdev, const char *buf, size_t count) { struct net_device *dev = to_net_dev(cdev); struct gfar_private *priv = netdev_priv(dev); unsigned int length = simple_strtoul(buf, NULL, 0); u32 temp; unsigned long flags; spin_lock_irqsave(&priv->rxlock, flags); if (length > priv->rx_buffer_size) return count; if (length == priv->rx_stash_size) return count; priv->rx_stash_size = length; temp = gfar_read(&priv->regs->attreli); temp &= ~ATTRELI_EL_MASK; temp |= ATTRELI_EL(length); gfar_write(&priv->regs->attreli, temp); /* Turn stashing on/off as appropriate */ temp = gfar_read(&priv->regs->attr); if (length) temp |= ATTR_BUFSTASH; else temp &= ~(ATTR_BUFSTASH); gfar_write(&priv->regs->attr, temp); spin_unlock_irqrestore(&priv->rxlock, flags); return count; }
/* configuration has to be done through the TSEC1 MIIM regs */ void write_phy_reg(struct net_device *dev, int mii_id, int regnum, int value) { struct gfar_private *priv = netdev_priv(dev); struct gfar *regbase = priv->phyregs; /* Set the PHY address and the register address we want to write */ gfar_write(®base->miimadd, (mii_id << 8) | regnum); /* Write out the value we want */ gfar_write(®base->miimcon, value); /* Wait for the transaction to finish */ while (gfar_read(®base->miimind) & MIIMIND_BUSY) cpu_relax(); }
/* Fill in an array of 64-bit statistics from various sources. * This array will be appended to the end of the ethtool_stats * structure, and returned to user space */ static void gfar_fill_stats(struct net_device *dev, struct ethtool_stats *dummy, u64 *buf) { int i; struct gfar_private *priv = netdev_priv(dev); struct gfar __iomem *regs = priv->gfargrp[0].regs; atomic64_t *extra = (atomic64_t *)&priv->extra_stats; for (i = 0; i < GFAR_EXTRA_STATS_LEN; i++) buf[i] = atomic64_read(&extra[i]); if (priv->device_flags & FSL_GIANFAR_DEV_HAS_RMON) { u32 __iomem *rmon = (u32 __iomem *) ®s->rmon; for (; i < GFAR_STATS_LEN; i++, rmon++) buf[i] = (u64) gfar_read(rmon); } }
static ssize_t gfar_set_bd_stash(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct gfar_private *priv = netdev_priv(to_net_dev(dev)); struct gfar __iomem *regs = priv->gfargrp[0].regs; int new_setting = 0; u32 temp; unsigned long flags; if (!(priv->device_flags & FSL_GIANFAR_DEV_HAS_BD_STASHING)) return count; /* Find out the new setting */ if (!strncmp("on", buf, count - 1) || !strncmp("1", buf, count - 1)) new_setting = 1; else if (!strncmp("off", buf, count - 1) || !strncmp("0", buf, count - 1)) new_setting = 0; else return count; local_irq_save(flags); lock_rx_qs(priv); /* Set the new stashing value */ priv->bd_stash_en = new_setting; temp = gfar_read(®s->attr); if (new_setting) temp |= ATTR_BDSTASH; else temp &= ~(ATTR_BDSTASH); gfar_write(®s->attr, temp); unlock_rx_qs(priv); local_irq_restore(flags); return count; }
/* Fill in an array of 64-bit statistics from various sources. * This array will be appended to the end of the ethtool_stats * structure, and returned to user space */ static void gfar_fill_stats(struct net_device *dev, struct ethtool_stats *dummy, u64 * buf) { int i; struct gfar_private *priv = netdev_priv(dev); u64 *extra = (u64 *) & priv->extra_stats; if (priv->device_flags & FSL_GIANFAR_DEV_HAS_RMON) { u32 __iomem *rmon = (u32 __iomem *) & priv->regs->rmon; struct gfar_stats *stats = (struct gfar_stats *) buf; for (i = 0; i < GFAR_RMON_LEN; i++) stats->rmon[i] = (u64) gfar_read(&rmon[i]); for (i = 0; i < GFAR_EXTRA_STATS_LEN; i++) stats->extra[i] = extra[i]; } else for (i = 0; i < GFAR_EXTRA_STATS_LEN; i++) buf[i] = extra[i]; }
static ssize_t gfar_set_bd_stash(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct gfar_private *priv = netdev_priv(to_net_dev(dev)); int new_setting = 0; u32 temp; unsigned long flags; if (!(priv->device_flags & FSL_GIANFAR_DEV_HAS_BD_STASHING)) return count; if (!strncmp("on", buf, count - 1) || !strncmp("1", buf, count - 1)) new_setting = 1; else if (!strncmp("off", buf, count - 1) || !strncmp("0", buf, count - 1)) new_setting = 0; else return count; spin_lock_irqsave(&priv->rxlock, flags); priv->bd_stash_en = new_setting; temp = gfar_read(&priv->regs->attr); if (new_setting) temp |= ATTR_BDSTASH; else temp &= ~(ATTR_BDSTASH); gfar_write(&priv->regs->attr, temp); spin_unlock_irqrestore(&priv->rxlock, flags); return count; }
/************************************************************************************************** Syntax: static void p2020_tsec_set_hardware_reg_configuration Parameters: Remarks: set p2020 etsec registers configurations for hardware Return Value: ***************************************************************************************************/ void p2020_tsec_set_hardware_reg_configuration(struct net_device *dev) { struct dev_mc_list *mc_ptr; struct gfar_private *priv = netdev_priv(dev); struct gfar *regs = priv->gfargrp[0].regs; u32 tempval; //Zoya [04 апр. 2014 г.] ///Ошибка! не работает??? // Set RCTRL to PROMISC mode printk("++Enable Promis mode for %s\n\r", dev->name); tempval = gfar_read(®s->rctrl); tempval |= RCTRL_PROM; gfar_write(®s->rctrl, tempval); /* printk("++Enable Multicast Frame for eth2\n\r++"); //Set multicast frames incoming packet gfar_write(®s->igaddr0, 0xffffffff); gfar_write(®s->igaddr1, 0xffffffff); gfar_write(®s->igaddr2, 0xffffffff); gfar_write(®s->igaddr3, 0xffffffff); gfar_write(®s->igaddr4, 0xffffffff); gfar_write(®s->igaddr5, 0xffffffff); gfar_write(®s->igaddr6, 0xffffffff); gfar_write(®s->igaddr7, 0xffffffff); gfar_write(®s->gaddr0, 0xffffffff); gfar_write(®s->gaddr1, 0xffffffff); gfar_write(®s->gaddr2, 0xffffffff); gfar_write(®s->gaddr3, 0xffffffff); gfar_write(®s->gaddr4, 0xffffffff); gfar_write(®s->gaddr5, 0xffffffff); gfar_write(®s->gaddr6, 0xffffffff); gfar_write(®s->gaddr7, 0xffffffff); */ }
static int gfar_spauseparam(struct net_device *dev, struct ethtool_pauseparam *epause) { struct gfar_private *priv = netdev_priv(dev); struct phy_device *phydev = priv->phydev; struct gfar __iomem *regs = priv->gfargrp[0].regs; u32 oldadv, newadv; if (!phydev) return -ENODEV; if (!(phydev->supported & SUPPORTED_Pause) || (!(phydev->supported & SUPPORTED_Asym_Pause) && (epause->rx_pause != epause->tx_pause))) return -EINVAL; priv->rx_pause_en = priv->tx_pause_en = 0; if (epause->rx_pause) { priv->rx_pause_en = 1; if (epause->tx_pause) { priv->tx_pause_en = 1; /* FLOW_CTRL_RX & TX */ newadv = ADVERTISED_Pause; } else /* FLOW_CTLR_RX */ newadv = ADVERTISED_Pause | ADVERTISED_Asym_Pause; } else if (epause->tx_pause) { priv->tx_pause_en = 1; /* FLOW_CTLR_TX */ newadv = ADVERTISED_Asym_Pause; } else newadv = 0; if (epause->autoneg) priv->pause_aneg_en = 1; else priv->pause_aneg_en = 0; oldadv = phydev->advertising & (ADVERTISED_Pause | ADVERTISED_Asym_Pause); if (oldadv != newadv) { phydev->advertising &= ~(ADVERTISED_Pause | ADVERTISED_Asym_Pause); phydev->advertising |= newadv; if (phydev->autoneg) /* inform link partner of our * new flow ctrl settings */ return phy_start_aneg(phydev); if (!epause->autoneg) { u32 tempval; tempval = gfar_read(®s->maccfg1); tempval &= ~(MACCFG1_TX_FLOW | MACCFG1_RX_FLOW); priv->tx_actual_en = 0; if (priv->tx_pause_en) { priv->tx_actual_en = 1; tempval |= MACCFG1_TX_FLOW; } if (priv->rx_pause_en) tempval |= MACCFG1_RX_FLOW; gfar_write(®s->maccfg1, tempval); } } return 0; }