diff options
author | Jeff Kirsher <jeffrey.t.kirsher@intel.com> | 2011-05-12 23:04:46 -0700 |
---|---|---|
committer | Jeff Kirsher <jeffrey.t.kirsher@intel.com> | 2011-08-11 02:33:43 -0700 |
commit | e689cf4a042772f727450035b102579b0c01bdc7 (patch) | |
tree | f2b17aa21b8358a8f7589fed46fa08688b439464 /drivers/net/niu.c | |
parent | 8efc91254fda97ee78e2e0b8e016120e664131de (diff) |
cassini/niu/sun*: Move the Sun drivers
Moves the Sun drivers into drivers/net/ethernet/sun/ and make
the necessary Kconfig and Makefile changes.
Oliver Hartkopp <socketcan@hartkopp.net> suggested removing the
sun* prefix on the driver names. This type of change I will
leave up to the driver maintainers.
CC: Sam Creasey <sammy@sammy.net>
CC: Adrian Sun <asun@darksunrising.com>
CC: Benjamin Herrenscmidt <benh@kernel.crashing.org>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
Diffstat (limited to 'drivers/net/niu.c')
-rw-r--r-- | drivers/net/niu.c | 10263 |
1 files changed, 0 insertions, 10263 deletions
diff --git a/drivers/net/niu.c b/drivers/net/niu.c deleted file mode 100644 index ed47585a686..00000000000 --- a/drivers/net/niu.c +++ /dev/null @@ -1,10263 +0,0 @@ -/* niu.c: Neptune ethernet driver. - * - * Copyright (C) 2007, 2008 David S. Miller (davem@davemloft.net) - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include <linux/module.h> -#include <linux/init.h> -#include <linux/interrupt.h> -#include <linux/pci.h> -#include <linux/dma-mapping.h> -#include <linux/netdevice.h> -#include <linux/ethtool.h> -#include <linux/etherdevice.h> -#include <linux/platform_device.h> -#include <linux/delay.h> -#include <linux/bitops.h> -#include <linux/mii.h> -#include <linux/if_ether.h> -#include <linux/if_vlan.h> -#include <linux/ip.h> -#include <linux/in.h> -#include <linux/ipv6.h> -#include <linux/log2.h> -#include <linux/jiffies.h> -#include <linux/crc32.h> -#include <linux/list.h> -#include <linux/slab.h> - -#include <linux/io.h> -#include <linux/of_device.h> - -#include "niu.h" - -#define DRV_MODULE_NAME "niu" -#define DRV_MODULE_VERSION "1.1" -#define DRV_MODULE_RELDATE "Apr 22, 2010" - -static char version[] __devinitdata = - DRV_MODULE_NAME ".c:v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n"; - -MODULE_AUTHOR("David S. Miller (davem@davemloft.net)"); -MODULE_DESCRIPTION("NIU ethernet driver"); -MODULE_LICENSE("GPL"); -MODULE_VERSION(DRV_MODULE_VERSION); - -#ifndef readq -static u64 readq(void __iomem *reg) -{ - return ((u64) readl(reg)) | (((u64) readl(reg + 4UL)) << 32); -} - -static void writeq(u64 val, void __iomem *reg) -{ - writel(val & 0xffffffff, reg); - writel(val >> 32, reg + 0x4UL); -} -#endif - -static DEFINE_PCI_DEVICE_TABLE(niu_pci_tbl) = { - {PCI_DEVICE(PCI_VENDOR_ID_SUN, 0xabcd)}, - {} -}; - -MODULE_DEVICE_TABLE(pci, niu_pci_tbl); - -#define NIU_TX_TIMEOUT (5 * HZ) - -#define nr64(reg) readq(np->regs + (reg)) -#define nw64(reg, val) writeq((val), np->regs + (reg)) - -#define nr64_mac(reg) readq(np->mac_regs + (reg)) -#define nw64_mac(reg, val) writeq((val), np->mac_regs + (reg)) - -#define nr64_ipp(reg) readq(np->regs + np->ipp_off + (reg)) -#define nw64_ipp(reg, val) writeq((val), np->regs + np->ipp_off + (reg)) - -#define nr64_pcs(reg) readq(np->regs + np->pcs_off + (reg)) -#define nw64_pcs(reg, val) writeq((val), np->regs + np->pcs_off + (reg)) - -#define nr64_xpcs(reg) readq(np->regs + np->xpcs_off + (reg)) -#define nw64_xpcs(reg, val) writeq((val), np->regs + np->xpcs_off + (reg)) - -#define NIU_MSG_DEFAULT (NETIF_MSG_DRV | NETIF_MSG_PROBE | NETIF_MSG_LINK) - -static int niu_debug; -static int debug = -1; -module_param(debug, int, 0); -MODULE_PARM_DESC(debug, "NIU debug level"); - -#define niu_lock_parent(np, flags) \ - spin_lock_irqsave(&np->parent->lock, flags) -#define niu_unlock_parent(np, flags) \ - spin_unlock_irqrestore(&np->parent->lock, flags) - -static int serdes_init_10g_serdes(struct niu *np); - -static int __niu_wait_bits_clear_mac(struct niu *np, unsigned long reg, - u64 bits, int limit, int delay) -{ - while (--limit >= 0) { - u64 val = nr64_mac(reg); - - if (!(val & bits)) - break; - udelay(delay); - } - if (limit < 0) - return -ENODEV; - return 0; -} - -static int __niu_set_and_wait_clear_mac(struct niu *np, unsigned long reg, - u64 bits, int limit, int delay, - const char *reg_name) -{ - int err; - - nw64_mac(reg, bits); - err = __niu_wait_bits_clear_mac(np, reg, bits, limit, delay); - if (err) - netdev_err(np->dev, "bits (%llx) of register %s would not clear, val[%llx]\n", - (unsigned long long)bits, reg_name, - (unsigned long long)nr64_mac(reg)); - return err; -} - -#define niu_set_and_wait_clear_mac(NP, REG, BITS, LIMIT, DELAY, REG_NAME) \ -({ BUILD_BUG_ON(LIMIT <= 0 || DELAY < 0); \ - __niu_set_and_wait_clear_mac(NP, REG, BITS, LIMIT, DELAY, REG_NAME); \ -}) - -static int __niu_wait_bits_clear_ipp(struct niu *np, unsigned long reg, - u64 bits, int limit, int delay) -{ - while (--limit >= 0) { - u64 val = nr64_ipp(reg); - - if (!(val & bits)) - break; - udelay(delay); - } - if (limit < 0) - return -ENODEV; - return 0; -} - -static int __niu_set_and_wait_clear_ipp(struct niu *np, unsigned long reg, - u64 bits, int limit, int delay, - const char *reg_name) -{ - int err; - u64 val; - - val = nr64_ipp(reg); - val |= bits; - nw64_ipp(reg, val); - - err = __niu_wait_bits_clear_ipp(np, reg, bits, limit, delay); - if (err) - netdev_err(np->dev, "bits (%llx) of register %s would not clear, val[%llx]\n", - (unsigned long long)bits, reg_name, - (unsigned long long)nr64_ipp(reg)); - return err; -} - -#define niu_set_and_wait_clear_ipp(NP, REG, BITS, LIMIT, DELAY, REG_NAME) \ -({ BUILD_BUG_ON(LIMIT <= 0 || DELAY < 0); \ - __niu_set_and_wait_clear_ipp(NP, REG, BITS, LIMIT, DELAY, REG_NAME); \ -}) - -static int __niu_wait_bits_clear(struct niu *np, unsigned long reg, - u64 bits, int limit, int delay) -{ - while (--limit >= 0) { - u64 val = nr64(reg); - - if (!(val & bits)) - break; - udelay(delay); - } - if (limit < 0) - return -ENODEV; - return 0; -} - -#define niu_wait_bits_clear(NP, REG, BITS, LIMIT, DELAY) \ -({ BUILD_BUG_ON(LIMIT <= 0 || DELAY < 0); \ - __niu_wait_bits_clear(NP, REG, BITS, LIMIT, DELAY); \ -}) - -static int __niu_set_and_wait_clear(struct niu *np, unsigned long reg, - u64 bits, int limit, int delay, - const char *reg_name) -{ - int err; - - nw64(reg, bits); - err = __niu_wait_bits_clear(np, reg, bits, limit, delay); - if (err) - netdev_err(np->dev, "bits (%llx) of register %s would not clear, val[%llx]\n", - (unsigned long long)bits, reg_name, - (unsigned long long)nr64(reg)); - return err; -} - -#define niu_set_and_wait_clear(NP, REG, BITS, LIMIT, DELAY, REG_NAME) \ -({ BUILD_BUG_ON(LIMIT <= 0 || DELAY < 0); \ - __niu_set_and_wait_clear(NP, REG, BITS, LIMIT, DELAY, REG_NAME); \ -}) - -static void niu_ldg_rearm(struct niu *np, struct niu_ldg *lp, int on) -{ - u64 val = (u64) lp->timer; - - if (on) - val |= LDG_IMGMT_ARM; - - nw64(LDG_IMGMT(lp->ldg_num), val); -} - -static int niu_ldn_irq_enable(struct niu *np, int ldn, int on) -{ - unsigned long mask_reg, bits; - u64 val; - - if (ldn < 0 || ldn > LDN_MAX) - return -EINVAL; - - if (ldn < 64) { - mask_reg = LD_IM0(ldn); - bits = LD_IM0_MASK; - } else { - mask_reg = LD_IM1(ldn - 64); - bits = LD_IM1_MASK; - } - - val = nr64(mask_reg); - if (on) - val &= ~bits; - else - val |= bits; - nw64(mask_reg, val); - - return 0; -} - -static int niu_enable_ldn_in_ldg(struct niu *np, struct niu_ldg *lp, int on) -{ - struct niu_parent *parent = np->parent; - int i; - - for (i = 0; i <= LDN_MAX; i++) { - int err; - - if (parent->ldg_map[i] != lp->ldg_num) - continue; - - err = niu_ldn_irq_enable(np, i, on); - if (err) - return err; - } - return 0; -} - -static int niu_enable_interrupts(struct niu *np, int on) -{ - int i; - - for (i = 0; i < np->num_ldg; i++) { - struct niu_ldg *lp = &np->ldg[i]; - int err; - - err = niu_enable_ldn_in_ldg(np, lp, on); - if (err) - return err; - } - for (i = 0; i < np->num_ldg; i++) - niu_ldg_rearm(np, &np->ldg[i], on); - - return 0; -} - -static u32 phy_encode(u32 type, int port) -{ - return type << (port * 2); -} - -static u32 phy_decode(u32 val, int port) -{ - return (val >> (port * 2)) & PORT_TYPE_MASK; -} - -static int mdio_wait(struct niu *np) -{ - int limit = 1000; - u64 val; - - while (--limit > 0) { - val = nr64(MIF_FRAME_OUTPUT); - if ((val >> MIF_FRAME_OUTPUT_TA_SHIFT) & 0x1) - return val & MIF_FRAME_OUTPUT_DATA; - - udelay(10); - } - - return -ENODEV; -} - -static int mdio_read(struct niu *np, int port, int dev, int reg) -{ - int err; - - nw64(MIF_FRAME_OUTPUT, MDIO_ADDR_OP(port, dev, reg)); - err = mdio_wait(np); - if (err < 0) - return err; - - nw64(MIF_FRAME_OUTPUT, MDIO_READ_OP(port, dev)); - return mdio_wait(np); -} - -static int mdio_write(struct niu *np, int port, int dev, int reg, int data) -{ - int err; - - nw64(MIF_FRAME_OUTPUT, MDIO_ADDR_OP(port, dev, reg)); - err = mdio_wait(np); - if (err < 0) - return err; - - nw64(MIF_FRAME_OUTPUT, MDIO_WRITE_OP(port, dev, data)); - err = mdio_wait(np); - if (err < 0) - return err; - - return 0; -} - -static int mii_read(struct niu *np, int port, int reg) -{ - nw64(MIF_FRAME_OUTPUT, MII_READ_OP(port, reg)); - return mdio_wait(np); -} - -static int mii_write(struct niu *np, int port, int reg, int data) -{ - int err; - - nw64(MIF_FRAME_OUTPUT, MII_WRITE_OP(port, reg, data)); - err = mdio_wait(np); - if (err < 0) - return err; - - return 0; -} - -static int esr2_set_tx_cfg(struct niu *np, unsigned long channel, u32 val) -{ - int err; - - err = mdio_write(np, np->port, NIU_ESR2_DEV_ADDR, - ESR2_TI_PLL_TX_CFG_L(channel), - val & 0xffff); - if (!err) - err = mdio_write(np, np->port, NIU_ESR2_DEV_ADDR, - ESR2_TI_PLL_TX_CFG_H(channel), - val >> 16); - return err; -} - -static int esr2_set_rx_cfg(struct niu *np, unsigned long channel, u32 val) -{ - int err; - - err = mdio_write(np, np->port, NIU_ESR2_DEV_ADDR, - ESR2_TI_PLL_RX_CFG_L(channel), - val & 0xffff); - if (!err) - err = mdio_write(np, np->port, NIU_ESR2_DEV_ADDR, - ESR2_TI_PLL_RX_CFG_H(channel), - val >> 16); - return err; -} - -/* Mode is always 10G fiber. */ -static int serdes_init_niu_10g_fiber(struct niu *np) -{ - struct niu_link_config *lp = &np->link_config; - u32 tx_cfg, rx_cfg; - unsigned long i; - - tx_cfg = (PLL_TX_CFG_ENTX | PLL_TX_CFG_SWING_1375MV); - rx_cfg = (PLL_RX_CFG_ENRX | PLL_RX_CFG_TERM_0P8VDDT | - PLL_RX_CFG_ALIGN_ENA | PLL_RX_CFG_LOS_LTHRESH | - PLL_RX_CFG_EQ_LP_ADAPTIVE); - - if (lp->loopback_mode == LOOPBACK_PHY) { - u16 test_cfg = PLL_TEST_CFG_LOOPBACK_CML_DIS; - - mdio_write(np, np->port, NIU_ESR2_DEV_ADDR, - ESR2_TI_PLL_TEST_CFG_L, test_cfg); - - tx_cfg |= PLL_TX_CFG_ENTEST; - rx_cfg |= PLL_RX_CFG_ENTEST; - } - - /* Initialize all 4 lanes of the SERDES. */ - for (i = 0; i < 4; i++) { - int err = esr2_set_tx_cfg(np, i, tx_cfg); - if (err) - return err; - } - - for (i = 0; i < 4; i++) { - int err = esr2_set_rx_cfg(np, i, rx_cfg); - if (err) - return err; - } - - return 0; -} - -static int serdes_init_niu_1g_serdes(struct niu *np) -{ - struct niu_link_config *lp = &np->link_config; - u16 pll_cfg, pll_sts; - int max_retry = 100; - u64 uninitialized_var(sig), mask, val; - u32 tx_cfg, rx_cfg; - unsigned long i; - int err; - - tx_cfg = (PLL_TX_CFG_ENTX | PLL_TX_CFG_SWING_1375MV | - PLL_TX_CFG_RATE_HALF); - rx_cfg = (PLL_RX_CFG_ENRX | PLL_RX_CFG_TERM_0P8VDDT | - PLL_RX_CFG_ALIGN_ENA | PLL_RX_CFG_LOS_LTHRESH | - PLL_RX_CFG_RATE_HALF); - - if (np->port == 0) - rx_cfg |= PLL_RX_CFG_EQ_LP_ADAPTIVE; - - if (lp->loopback_mode == LOOPBACK_PHY) { - u16 test_cfg = PLL_TEST_CFG_LOOPBACK_CML_DIS; - - mdio_write(np, np->port, NIU_ESR2_DEV_ADDR, - ESR2_TI_PLL_TEST_CFG_L, test_cfg); - - tx_cfg |= PLL_TX_CFG_ENTEST; - rx_cfg |= PLL_RX_CFG_ENTEST; - } - - /* Initialize PLL for 1G */ - pll_cfg = (PLL_CFG_ENPLL | PLL_CFG_MPY_8X); - - err = mdio_write(np, np->port, NIU_ESR2_DEV_ADDR, - ESR2_TI_PLL_CFG_L, pll_cfg); - if (err) { - netdev_err(np->dev, "NIU Port %d %s() mdio write to ESR2_TI_PLL_CFG_L failed\n", - np->port, __func__); - return err; - } - - pll_sts = PLL_CFG_ENPLL; - - err = mdio_write(np, np->port, NIU_ESR2_DEV_ADDR, - ESR2_TI_PLL_STS_L, pll_sts); - if (err) { - netdev_err(np->dev, "NIU Port %d %s() mdio write to ESR2_TI_PLL_STS_L failed\n", - np->port, __func__); - return err; - } - - udelay(200); - - /* Initialize all 4 lanes of the SERDES. */ - for (i = 0; i < 4; i++) { - err = esr2_set_tx_cfg(np, i, tx_cfg); - if (err) - return err; - } - - for (i = 0; i < 4; i++) { - err = esr2_set_rx_cfg(np, i, rx_cfg); - if (err) - return err; - } - - switch (np->port) { - case 0: - val = (ESR_INT_SRDY0_P0 | ESR_INT_DET0_P0); - mask = val; - break; - - case 1: - val = (ESR_INT_SRDY0_P1 | ESR_INT_DET0_P1); - mask = val; - break; - - default: - return -EINVAL; - } - - while (max_retry--) { - sig = nr64(ESR_INT_SIGNALS); - if ((sig & mask) == val) - break; - - mdelay(500); - } - - if ((sig & mask) != val) { - netdev_err(np->dev, "Port %u signal bits [%08x] are not [%08x]\n", - np->port, (int)(sig & mask), (int)val); - return -ENODEV; - } - - return 0; -} - -static int serdes_init_niu_10g_serdes(struct niu *np) -{ - struct niu_link_config *lp = &np->link_config; - u32 tx_cfg, rx_cfg, pll_cfg, pll_sts; - int max_retry = 100; - u64 uninitialized_var(sig), mask, val; - unsigned long i; - int err; - - tx_cfg = (PLL_TX_CFG_ENTX | PLL_TX_CFG_SWING_1375MV); - rx_cfg = (PLL_RX_CFG_ENRX | PLL_RX_CFG_TERM_0P8VDDT | - PLL_RX_CFG_ALIGN_ENA | PLL_RX_CFG_LOS_LTHRESH | - PLL_RX_CFG_EQ_LP_ADAPTIVE); - - if (lp->loopback_mode == LOOPBACK_PHY) { - u16 test_cfg = PLL_TEST_CFG_LOOPBACK_CML_DIS; - - mdio_write(np, np->port, NIU_ESR2_DEV_ADDR, - ESR2_TI_PLL_TEST_CFG_L, test_cfg); - - tx_cfg |= PLL_TX_CFG_ENTEST; - rx_cfg |= PLL_RX_CFG_ENTEST; - } - - /* Initialize PLL for 10G */ - pll_cfg = (PLL_CFG_ENPLL | PLL_CFG_MPY_10X); - - err = mdio_write(np, np->port, NIU_ESR2_DEV_ADDR, - ESR2_TI_PLL_CFG_L, pll_cfg & 0xffff); - if (err) { - netdev_err(np->dev, "NIU Port %d %s() mdio write to ESR2_TI_PLL_CFG_L failed\n", - np->port, __func__); - return err; - } - - pll_sts = PLL_CFG_ENPLL; - - err = mdio_write(np, np->port, NIU_ESR2_DEV_ADDR, - ESR2_TI_PLL_STS_L, pll_sts & 0xffff); - if (err) { - netdev_err(np->dev, "NIU Port %d %s() mdio write to ESR2_TI_PLL_STS_L failed\n", - np->port, __func__); - return err; - } - - udelay(200); - - /* Initialize all 4 lanes of the SERDES. */ - for (i = 0; i < 4; i++) { - err = esr2_set_tx_cfg(np, i, tx_cfg); - if (err) - return err; - } - - for (i = 0; i < 4; i++) { - err = esr2_set_rx_cfg(np, i, rx_cfg); - if (err) - return err; - } - - /* check if serdes is ready */ - - switch (np->port) { - case 0: - mask = ESR_INT_SIGNALS_P0_BITS; - val = (ESR_INT_SRDY0_P0 | - ESR_INT_DET0_P0 | - ESR_INT_XSRDY_P0 | - ESR_INT_XDP_P0_CH3 | - ESR_INT_XDP_P0_CH2 | - ESR_INT_XDP_P0_CH1 | - ESR_INT_XDP_P0_CH0); - break; - - case 1: - mask = ESR_INT_SIGNALS_P1_BITS; - val = (ESR_INT_SRDY0_P1 | - ESR_INT_DET0_P1 | - ESR_INT_XSRDY_P1 | - ESR_INT_XDP_P1_CH3 | - ESR_INT_XDP_P1_CH2 | - ESR_INT_XDP_P1_CH1 | - ESR_INT_XDP_P1_CH0); - break; - - default: - return -EINVAL; - } - - while (max_retry--) { - sig = nr64(ESR_INT_SIGNALS); - if ((sig & mask) == val) - break; - - mdelay(500); - } - - if ((sig & mask) != val) { - pr_info("NIU Port %u signal bits [%08x] are not [%08x] for 10G...trying 1G\n", - np->port, (int)(sig & mask), (int)val); - - /* 10G failed, try initializing at 1G */ - err = serdes_init_niu_1g_serdes(np); - if (!err) { - np->flags &= ~NIU_FLAGS_10G; - np->mac_xcvr = MAC_XCVR_PCS; - } else { - netdev_err(np->dev, "Port %u 10G/1G SERDES Link Failed\n", - np->port); - return -ENODEV; - } - } - return 0; -} - -static int esr_read_rxtx_ctrl(struct niu *np, unsigned long chan, u32 *val) -{ - int err; - - err = mdio_read(np, np->port, NIU_ESR_DEV_ADDR, ESR_RXTX_CTRL_L(chan)); - if (err >= 0) { - *val = (err & 0xffff); - err = mdio_read(np, np->port, NIU_ESR_DEV_ADDR, - ESR_RXTX_CTRL_H(chan)); - if (err >= 0) - *val |= ((err & 0xffff) << 16); - err = 0; - } - return err; -} - -static int esr_read_glue0(struct niu *np, unsigned long chan, u32 *val) -{ - int err; - - err = mdio_read(np, np->port, NIU_ESR_DEV_ADDR, - ESR_GLUE_CTRL0_L(chan)); - if (err >= 0) { - *val = (err & 0xffff); - err = mdio_read(np, np->port, NIU_ESR_DEV_ADDR, - ESR_GLUE_CTRL0_H(chan)); - if (err >= 0) { - *val |= ((err & 0xffff) << 16); - err = 0; - } - } - return err; -} - -static int esr_read_reset(struct niu *np, u32 *val) -{ - int err; - - err = mdio_read(np, np->port, NIU_ESR_DEV_ADDR, - ESR_RXTX_RESET_CTRL_L); - if (err >= 0) { - *val = (err & 0xffff); - err = mdio_read(np, np->port, NIU_ESR_DEV_ADDR, - ESR_RXTX_RESET_CTRL_H); - if (err >= 0) { - *val |= ((err & 0xffff) << 16); - err = 0; - } - } - return err; -} - -static int esr_write_rxtx_ctrl(struct niu *np, unsigned long chan, u32 val) -{ - int err; - - err = mdio_write(np, np->port, NIU_ESR_DEV_ADDR, - ESR_RXTX_CTRL_L(chan), val & 0xffff); - if (!err) - err = mdio_write(np, np->port, NIU_ESR_DEV_ADDR, - ESR_RXTX_CTRL_H(chan), (val >> 16)); - return err; -} - -static int esr_write_glue0(struct niu *np, unsigned long chan, u32 val) -{ - int err; - - err = mdio_write(np, np->port, NIU_ESR_DEV_ADDR, - ESR_GLUE_CTRL0_L(chan), val & 0xffff); - if (!err) - err = mdio_write(np, np->port, NIU_ESR_DEV_ADDR, - ESR_GLUE_CTRL0_H(chan), (val >> 16)); - return err; -} - -static int esr_reset(struct niu *np) -{ - u32 uninitialized_var(reset); - int err; - - err = mdio_write(np, np->port, NIU_ESR_DEV_ADDR, - ESR_RXTX_RESET_CTRL_L, 0x0000); - if (err) - return err; - err = mdio_write(np, np->port, NIU_ESR_DEV_ADDR, - ESR_RXTX_RESET_CTRL_H, 0xffff); - if (err) - return err; - udelay(200); - - err = mdio_write(np, np->port, NIU_ESR_DEV_ADDR, - ESR_RXTX_RESET_CTRL_L, 0xffff); - if (err) - return err; - udelay(200); - - err = mdio_write(np, np->port, NIU_ESR_DEV_ADDR, - ESR_RXTX_RESET_CTRL_H, 0x0000); - if (err) - return err; - udelay(200); - - err = esr_read_reset(np, &reset); - if (err) - return err; - if (reset != 0) { - netdev_err(np->dev, "Port %u ESR_RESET did not clear [%08x]\n", - np->port, reset); - return -ENODEV; - } - - return 0; -} - -static int serdes_init_10g(struct niu *np) -{ - struct niu_link_config *lp = &np->link_config; - unsigned long ctrl_reg, test_cfg_reg, i; - u64 ctrl_val, test_cfg_val, sig, mask, val; - int err; - - switch (np->port) { - case 0: - ctrl_reg = ENET_SERDES_0_CTRL_CFG; - test_cfg_reg = ENET_SERDES_0_TEST_CFG; - break; - case 1: - ctrl_reg = ENET_SERDES_1_CTRL_CFG; - test_cfg_reg = ENET_SERDES_1_TEST_CFG; - break; - - default: - return -EINVAL; - } - ctrl_val = (ENET_SERDES_CTRL_SDET_0 | - ENET_SERDES_CTRL_SDET_1 | - ENET_SERDES_CTRL_SDET_2 | - ENET_SERDES_CTRL_SDET_3 | - (0x5 << ENET_SERDES_CTRL_EMPH_0_SHIFT) | - (0x5 << ENET_SERDES_CTRL_EMPH_1_SHIFT) | - (0x5 << ENET_SERDES_CTRL_EMPH_2_SHIFT) | - (0x5 << ENET_SERDES_CTRL_EMPH_3_SHIFT) | - (0x1 << ENET_SERDES_CTRL_LADJ_0_SHIFT) | - (0x1 << ENET_SERDES_CTRL_LADJ_1_SHIFT) | - (0x1 << ENET_SERDES_CTRL_LADJ_2_SHIFT) | - (0x1 << ENET_SERDES_CTRL_LADJ_3_SHIFT)); - test_cfg_val = 0; - - if (lp->loopback_mode == LOOPBACK_PHY) { - test_cfg_val |= ((ENET_TEST_MD_PAD_LOOPBACK << - ENET_SERDES_TEST_MD_0_SHIFT) | - (ENET_TEST_MD_PAD_LOOPBACK << - ENET_SERDES_TEST_MD_1_SHIFT) | - (ENET_TEST_MD_PAD_LOOPBACK << - ENET_SERDES_TEST_MD_2_SHIFT) | - (ENET_TEST_MD_PAD_LOOPBACK << - ENET_SERDES_TEST_MD_3_SHIFT)); - } - - nw64(ctrl_reg, ctrl_val); - nw64(test_cfg_reg, test_cfg_val); - - /* Initialize all 4 lanes of the SERDES. */ - for (i = 0; i < 4; i++) { - u32 rxtx_ctrl, glue0; - - err = esr_read_rxtx_ctrl(np, i, &rxtx_ctrl); - if (err) - return err; - err = esr_read_glue0(np, i, &glue0); - if (err) - return err; - - rxtx_ctrl &= ~(ESR_RXTX_CTRL_VMUXLO); - rxtx_ctrl |= (ESR_RXTX_CTRL_ENSTRETCH | - (2 << ESR_RXTX_CTRL_VMUXLO_SHIFT)); - - glue0 &= ~(ESR_GLUE_CTRL0_SRATE | - ESR_GLUE_CTRL0_THCNT | - ESR_GLUE_CTRL0_BLTIME); - glue0 |= (ESR_GLUE_CTRL0_RXLOSENAB | - (0xf << ESR_GLUE_CTRL0_SRATE_SHIFT) | - (0xff << ESR_GLUE_CTRL0_THCNT_SHIFT) | - (BLTIME_300_CYCLES << - ESR_GLUE_CTRL0_BLTIME_SHIFT)); - - err = esr_write_rxtx_ctrl(np, i, rxtx_ctrl); - if (err) - return err; - err = esr_write_glue0(np, i, glue0); - if (err) - return err; - } - - err = esr_reset(np); - if (err) - return err; - - sig = nr64(ESR_INT_SIGNALS); - switch (np->port) { - case 0: - mask = ESR_INT_SIGNALS_P0_BITS; - val = (ESR_INT_SRDY0_P0 | - ESR_INT_DET0_P0 | - ESR_INT_XSRDY_P0 | - ESR_INT_XDP_P0_CH3 | - ESR_INT_XDP_P0_CH2 | - ESR_INT_XDP_P0_CH1 | - ESR_INT_XDP_P0_CH0); - break; - - case 1: - mask = ESR_INT_SIGNALS_P1_BITS; - val = (ESR_INT_SRDY0_P1 | - ESR_INT_DET0_P1 | - ESR_INT_XSRDY_P1 | - ESR_INT_XDP_P1_CH3 | - ESR_INT_XDP_P1_CH2 | - ESR_INT_XDP_P1_CH1 | - ESR_INT_XDP_P1_CH0); - break; - - default: - return -EINVAL; - } - - if ((sig & mask) != val) { - if (np->flags & NIU_FLAGS_HOTPLUG_PHY) { - np->flags &= ~NIU_FLAGS_HOTPLUG_PHY_PRESENT; - return 0; - } - netdev_err(np->dev, "Port %u signal bits [%08x] are not [%08x]\n", - np->port, (int)(sig & mask), (int)val); - return -ENODEV; - } - if (np->flags & NIU_FLAGS_HOTPLUG_PHY) - np->flags |= NIU_FLAGS_HOTPLUG_PHY_PRESENT; - return 0; -} - -static int serdes_init_1g(struct niu *np) -{ - u64 val; - - val = nr64(ENET_SERDES_1_PLL_CFG); - val &= ~ENET_SERDES_PLL_FBDIV2; - switch (np->port) { - case 0: - val |= ENET_SERDES_PLL_HRATE0; - break; - case 1: - val |= ENET_SERDES_PLL_HRATE1; - break; - case 2: - val |= ENET_SERDES_PLL_HRATE2; - break; - case 3: - val |= ENET_SERDES_PLL_HRATE3; - break; - default: - return -EINVAL; - } - nw64(ENET_SERDES_1_PLL_CFG, val); - - return 0; -} - -static int serdes_init_1g_serdes(struct niu *np) -{ - struct niu_link_config *lp = &np->link_config; - unsigned long ctrl_reg, test_cfg_reg, pll_cfg, i; - u64 ctrl_val, test_cfg_val, sig, mask, val; - int err; - u64 reset_val, val_rd; - - val = ENET_SERDES_PLL_HRATE0 | ENET_SERDES_PLL_HRATE1 | - ENET_SERDES_PLL_HRATE2 | ENET_SERDES_PLL_HRATE3 | - ENET_SERDES_PLL_FBDIV0; - switch (np->port) { - case 0: - reset_val = ENET_SERDES_RESET_0; - ctrl_reg = ENET_SERDES_0_CTRL_CFG; - test_cfg_reg = ENET_SERDES_0_TEST_CFG; - pll_cfg = ENET_SERDES_0_PLL_CFG; - break; - case 1: - reset_val = ENET_SERDES_RESET_1; - ctrl_reg = ENET_SERDES_1_CTRL_CFG; - test_cfg_reg = ENET_SERDES_1_TEST_CFG; - pll_cfg = ENET_SERDES_1_PLL_CFG; - break; - - default: - return -EINVAL; - } - ctrl_val = (ENET_SERDES_CTRL_SDET_0 | - ENET_SERDES_CTRL_SDET_1 | - ENET_SERDES_CTRL_SDET_2 | - ENET_SERDES_CTRL_SDET_3 | - (0x5 << ENET_SERDES_CTRL_EMPH_0_SHIFT) | - (0x5 << ENET_SERDES_CTRL_EMPH_1_SHIFT) | - (0x5 << ENET_SERDES_CTRL_EMPH_2_SHIFT) | - (0x5 << ENET_SERDES_CTRL_EMPH_3_SHIFT) | - (0x1 << ENET_SERDES_CTRL_LADJ_0_SHIFT) | - (0x1 << ENET_SERDES_CTRL_LADJ_1_SHIFT) | - (0x1 << ENET_SERDES_CTRL_LADJ_2_SHIFT) | - (0x1 << ENET_SERDES_CTRL_LADJ_3_SHIFT)); - test_cfg_val = 0; - - if (lp->loopback_mode == LOOPBACK_PHY) { - test_cfg_val |= ((ENET_TEST_MD_PAD_LOOPBACK << - ENET_SERDES_TEST_MD_0_SHIFT) | - (ENET_TEST_MD_PAD_LOOPBACK << - ENET_SERDES_TEST_MD_1_SHIFT) | - (ENET_TEST_MD_PAD_LOOPBACK << - ENET_SERDES_TEST_MD_2_SHIFT) | - (ENET_TEST_MD_PAD_LOOPBACK << - ENET_SERDES_TEST_MD_3_SHIFT)); - } - - nw64(ENET_SERDES_RESET, reset_val); - mdelay(20); - val_rd = nr64(ENET_SERDES_RESET); - val_rd &= ~reset_val; - nw64(pll_cfg, val); - nw64(ctrl_reg, ctrl_val); - nw64(test_cfg_reg, test_cfg_val); - nw64(ENET_SERDES_RESET, val_rd); - mdelay(2000); - - /* Initialize all 4 lanes of the SERDES. */ - for (i = 0; i < 4; i++) { - u32 rxtx_ctrl, glue0; - - err = esr_read_rxtx_ctrl(np, i, &rxtx_ctrl); - if (err) - return err; - err = esr_read_glue0(np, i, &glue0); - if (err) - return err; - - rxtx_ctrl &= ~(ESR_RXTX_CTRL_VMUXLO); - rxtx_ctrl |= (ESR_RXTX_CTRL_ENSTRETCH | - (2 << ESR_RXTX_CTRL_VMUXLO_SHIFT)); - - glue0 &= ~(ESR_GLUE_CTRL0_SRATE | - ESR_GLUE_CTRL0_THCNT | - ESR_GLUE_CTRL0_BLTIME); - glue0 |= (ESR_GLUE_CTRL0_RXLOSENAB | - (0xf << ESR_GLUE_CTRL0_SRATE_SHIFT) | - (0xff << ESR_GLUE_CTRL0_THCNT_SHIFT) | - (BLTIME_300_CYCLES << - ESR_GLUE_CTRL0_BLTIME_SHIFT)); - - err = esr_write_rxtx_ctrl(np, i, rxtx_ctrl); - if (err) - return err; - err = esr_write_glue0(np, i, glue0); - if (err) - return err; - } - - - sig = nr64(ESR_INT_SIGNALS); - switch (np->port) { - case 0: - val = (ESR_INT_SRDY0_P0 | ESR_INT_DET0_P0); - mask = val; - break; - - case 1: - val = (ESR_INT_SRDY0_P1 | ESR_INT_DET0_P1); - mask = val; - break; - - default: - return -EINVAL; - } - - if ((sig & mask) != val) { - netdev_err(np->dev, "Port %u signal bits [%08x] are not [%08x]\n", - np->port, (int)(sig & mask), (int)val); - return -ENODEV; - } - - return 0; -} - -static int link_status_1g_serdes(struct niu *np, int *link_up_p) -{ - struct niu_link_config *lp = &np->link_config; - int link_up; - u64 val; - u16 current_speed; - unsigned long flags; - u8 current_duplex; - - link_up = 0; - current_speed = SPEED_INVALID; - current_duplex = DUPLEX_INVALID; - - spin_lock_irqsave(&np->lock, flags); - - val = nr64_pcs(PCS_MII_STAT); - - if (val & PCS_MII_STAT_LINK_STATUS) { - link_up = 1; - current_speed = SPEED_1000; - current_duplex = DUPLEX_FULL; - } - - lp->active_speed = current_speed; - lp->active_duplex = current_duplex; - spin_unlock_irqrestore(&np->lock, flags); - - *link_up_p = link_up; - return 0; -} - -static int link_status_10g_serdes(struct niu *np, int *link_up_p) -{ - unsigned long flags; - struct niu_link_config *lp = &np->link_config; - int link_up = 0; - int link_ok = 1; - u64 val, val2; - u16 current_speed; - u8 current_duplex; - - if (!(np->flags & NIU_FLAGS_10G)) - return link_status_1g_serdes(np, link_up_p); - - current_speed = SPEED_INVALID; - current_duplex = DUPLEX_INVALID; - spin_lock_irqsave(&np->lock, flags); - - val = nr64_xpcs(XPCS_STATUS(0)); - val2 = nr64_mac(XMAC_INTER2); - if (val2 & 0x01000000) - link_ok = 0; - - if ((val & 0x1000ULL) && link_ok) { - link_up = 1; - current_speed = SPEED_10000; - current_duplex = DUPLEX_FULL; - } - lp->active_speed = current_speed; - lp->active_duplex = current_duplex; - spin_unlock_irqrestore(&np->lock, flags); - *link_up_p = link_up; - return 0; -} - -static int link_status_mii(struct niu *np, int *link_up_p) -{ - struct niu_link_config *lp = &np->link_config; - int err; - int bmsr, advert, ctrl1000, stat1000, lpa, bmcr, estatus; - int supported, advertising, active_speed, active_duplex; - - err = mii_read(np, np->phy_addr, MII_BMCR); - if (unlikely(err < 0)) - return err; - bmcr = err; - - err = mii_read(np, np->phy_addr, MII_BMSR); - if (unlikely(err < 0)) - return err; - bmsr = err; - - err = mii_read(np, np->phy_addr, MII_ADVERTISE); - if (unlikely(err < 0)) - return err; - advert = err; - - err = mii_read(np, np->phy_addr, MII_LPA); - if (unlikely(err < 0)) - return err; - lpa = err; - - if (likely(bmsr & BMSR_ESTATEN)) { - err = mii_read(np, np->phy_addr, MII_ESTATUS); - if (unlikely(err < 0)) - return err; - estatus = err; - - err = mii_read(np, np->phy_addr, MII_CTRL1000); - if (unlikely(err < 0)) - return err; - ctrl1000 = err; - - err = mii_read(np, np->phy_addr, MII_STAT1000); - if (unlikely(err < 0)) - return err; - stat1000 = err; - } else - estatus = ctrl1000 = stat1000 = 0; - - supported = 0; - if (bmsr & BMSR_ANEGCAPABLE) - supported |= SUPPORTED_Autoneg; - if (bmsr & BMSR_10HALF) - supported |= SUPPORTED_10baseT_Half; - if (bmsr & BMSR_10FULL) - supported |= SUPPORTED_10baseT_Full; - if (bmsr & BMSR_100HALF) - supported |= SUPPORTED_100baseT_Half; - if (bmsr & BMSR_100FULL) - supported |= SUPPORTED_100baseT_Full; - if (estatus & ESTATUS_1000_THALF) - supported |= SUPPORTED_1000baseT_Half; - if (estatus & ESTATUS_1000_TFULL) - supported |= SUPPORTED_1000baseT_Full; - lp->supported = supported; - - advertising = 0; - if (advert & ADVERTISE_10HALF) - advertising |= ADVERTISED_10baseT_Half; - if (advert & ADVERTISE_10FULL) - advertising |= ADVERTISED_10baseT_Full; - if (advert & ADVERTISE_100HALF) - advertising |= ADVERTISED_100baseT_Half; - if (advert & ADVERTISE_100FULL) - advertising |= ADVERTISED_100baseT_Full; - if (ctrl1000 & ADVERTISE_1000HALF) - advertising |= ADVERTISED_1000baseT_Half; - if (ctrl1000 & ADVERTISE_1000FULL) - advertising |= ADVERTISED_1000baseT_Full; - - if (bmcr & BMCR_ANENABLE) { - int neg, neg1000; - - lp->active_autoneg = 1; - advertising |= ADVERTISED_Autoneg; - - neg = advert & lpa; - neg1000 = (ctrl1000 << 2) & stat1000; - - if (neg1000 & (LPA_1000FULL | LPA_1000HALF)) - active_speed = SPEED_1000; - else if (neg & LPA_100) - active_speed = SPEED_100; - else if (neg & (LPA_10HALF | LPA_10FULL)) - active_speed = SPEED_10; - else - active_speed = SPEED_INVALID; - - if ((neg1000 & LPA_1000FULL) || (neg & LPA_DUPLEX)) - active_duplex = DUPLEX_FULL; - else if (active_speed != SPEED_INVALID) - active_duplex = DUPLEX_HALF; - else - active_duplex = DUPLEX_INVALID; - } else { - lp->active_autoneg = 0; - - if ((bmcr & BMCR_SPEED1000) && !(bmcr & BMCR_SPEED100)) - active_speed = SPEED_1000; - else if (bmcr & BMCR_SPEED100) - active_speed = SPEED_100; - else - active_speed = SPEED_10; - - if (bmcr & BMCR_FULLDPLX) - active_duplex = DUPLEX_FULL; - else - active_duplex = DUPLEX_HALF; - } - - lp->active_advertising = advertising; - lp->active_speed = active_speed; - lp->active_duplex = active_duplex; - *link_up_p = !!(bmsr & BMSR_LSTATUS); - - return 0; -} - -static int link_status_1g_rgmii(struct niu *np, int *link_up_p) -{ - struct niu_link_config *lp = &np->link_config; - u16 current_speed, bmsr; - unsigned long flags; - u8 current_duplex; - int err, link_up; - - link_up = 0; - current_speed = SPEED_INVALID; - current_duplex = DUPLEX_INVALID; - - spin_lock_irqsave(&np->lock, flags); - - err = -EINVAL; - - err = mii_read(np, np->phy_addr, MII_BMSR); - if (err < 0) - goto out; - - bmsr = err; - if (bmsr & BMSR_LSTATUS) { |