aboutsummaryrefslogtreecommitdiff
path: root/drivers/net/niu.c
diff options
context:
space:
mode:
authorJeff Kirsher <jeffrey.t.kirsher@intel.com>2011-05-12 23:04:46 -0700
committerJeff Kirsher <jeffrey.t.kirsher@intel.com>2011-08-11 02:33:43 -0700
commite689cf4a042772f727450035b102579b0c01bdc7 (patch)
treef2b17aa21b8358a8f7589fed46fa08688b439464 /drivers/net/niu.c
parent8efc91254fda97ee78e2e0b8e016120e664131de (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.c10263
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) {