linux/drivers/net/ethernet/chelsio/cxgb/subr.c
<<
>>
Prefs
   1/*****************************************************************************
   2 *                                                                           *
   3 * File: subr.c                                                              *
   4 * $Revision: 1.27 $                                                         *
   5 * $Date: 2005/06/22 01:08:36 $                                              *
   6 * Description:                                                              *
   7 *  Various subroutines (intr,pio,etc.) used by Chelsio 10G Ethernet driver. *
   8 *  part of the Chelsio 10Gb Ethernet Driver.                                *
   9 *                                                                           *
  10 * This program is free software; you can redistribute it and/or modify      *
  11 * it under the terms of the GNU General Public License, version 2, as       *
  12 * published by the Free Software Foundation.                                *
  13 *                                                                           *
  14 * You should have received a copy of the GNU General Public License along   *
  15 * with this program; if not, write to the Free Software Foundation, Inc.,   *
  16 * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.                 *
  17 *                                                                           *
  18 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED    *
  19 * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF      *
  20 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.                     *
  21 *                                                                           *
  22 * http://www.chelsio.com                                                    *
  23 *                                                                           *
  24 * Copyright (c) 2003 - 2005 Chelsio Communications, Inc.                    *
  25 * All rights reserved.                                                      *
  26 *                                                                           *
  27 * Maintainers: maintainers@chelsio.com                                      *
  28 *                                                                           *
  29 * Authors: Dimitrios Michailidis   <dm@chelsio.com>                         *
  30 *          Tina Yang               <tainay@chelsio.com>                     *
  31 *          Felix Marti             <felix@chelsio.com>                      *
  32 *          Scott Bardone           <sbardone@chelsio.com>                   *
  33 *          Kurt Ottaway            <kottaway@chelsio.com>                   *
  34 *          Frank DiMambro          <frank@chelsio.com>                      *
  35 *                                                                           *
  36 * History:                                                                  *
  37 *                                                                           *
  38 ****************************************************************************/
  39
  40#include "common.h"
  41#include "elmer0.h"
  42#include "regs.h"
  43#include "gmac.h"
  44#include "cphy.h"
  45#include "sge.h"
  46#include "tp.h"
  47#include "espi.h"
  48
  49/**
  50 *      t1_wait_op_done - wait until an operation is completed
  51 *      @adapter: the adapter performing the operation
  52 *      @reg: the register to check for completion
  53 *      @mask: a single-bit field within @reg that indicates completion
  54 *      @polarity: the value of the field when the operation is completed
  55 *      @attempts: number of check iterations
  56 *      @delay: delay in usecs between iterations
  57 *
  58 *      Wait until an operation is completed by checking a bit in a register
  59 *      up to @attempts times.  Returns %0 if the operation completes and %1
  60 *      otherwise.
  61 */
  62static int t1_wait_op_done(adapter_t *adapter, int reg, u32 mask, int polarity,
  63                           int attempts, int delay)
  64{
  65        while (1) {
  66                u32 val = readl(adapter->regs + reg) & mask;
  67
  68                if (!!val == polarity)
  69                        return 0;
  70                if (--attempts == 0)
  71                        return 1;
  72                if (delay)
  73                        udelay(delay);
  74        }
  75}
  76
  77#define TPI_ATTEMPTS 50
  78
  79/*
  80 * Write a register over the TPI interface (unlocked and locked versions).
  81 */
  82int __t1_tpi_write(adapter_t *adapter, u32 addr, u32 value)
  83{
  84        int tpi_busy;
  85
  86        writel(addr, adapter->regs + A_TPI_ADDR);
  87        writel(value, adapter->regs + A_TPI_WR_DATA);
  88        writel(F_TPIWR, adapter->regs + A_TPI_CSR);
  89
  90        tpi_busy = t1_wait_op_done(adapter, A_TPI_CSR, F_TPIRDY, 1,
  91                                   TPI_ATTEMPTS, 3);
  92        if (tpi_busy)
  93                pr_alert("%s: TPI write to 0x%x failed\n",
  94                         adapter->name, addr);
  95        return tpi_busy;
  96}
  97
  98int t1_tpi_write(adapter_t *adapter, u32 addr, u32 value)
  99{
 100        int ret;
 101
 102        spin_lock(&adapter->tpi_lock);
 103        ret = __t1_tpi_write(adapter, addr, value);
 104        spin_unlock(&adapter->tpi_lock);
 105        return ret;
 106}
 107
 108/*
 109 * Read a register over the TPI interface (unlocked and locked versions).
 110 */
 111int __t1_tpi_read(adapter_t *adapter, u32 addr, u32 *valp)
 112{
 113        int tpi_busy;
 114
 115        writel(addr, adapter->regs + A_TPI_ADDR);
 116        writel(0, adapter->regs + A_TPI_CSR);
 117
 118        tpi_busy = t1_wait_op_done(adapter, A_TPI_CSR, F_TPIRDY, 1,
 119                                   TPI_ATTEMPTS, 3);
 120        if (tpi_busy)
 121                pr_alert("%s: TPI read from 0x%x failed\n",
 122                         adapter->name, addr);
 123        else
 124                *valp = readl(adapter->regs + A_TPI_RD_DATA);
 125        return tpi_busy;
 126}
 127
 128int t1_tpi_read(adapter_t *adapter, u32 addr, u32 *valp)
 129{
 130        int ret;
 131
 132        spin_lock(&adapter->tpi_lock);
 133        ret = __t1_tpi_read(adapter, addr, valp);
 134        spin_unlock(&adapter->tpi_lock);
 135        return ret;
 136}
 137
 138/*
 139 * Set a TPI parameter.
 140 */
 141static void t1_tpi_par(adapter_t *adapter, u32 value)
 142{
 143        writel(V_TPIPAR(value), adapter->regs + A_TPI_PAR);
 144}
 145
 146/*
 147 * Called when a port's link settings change to propagate the new values to the
 148 * associated PHY and MAC.  After performing the common tasks it invokes an
 149 * OS-specific handler.
 150 */
 151void t1_link_changed(adapter_t *adapter, int port_id)
 152{
 153        int link_ok, speed, duplex, fc;
 154        struct cphy *phy = adapter->port[port_id].phy;
 155        struct link_config *lc = &adapter->port[port_id].link_config;
 156
 157        phy->ops->get_link_status(phy, &link_ok, &speed, &duplex, &fc);
 158
 159        lc->speed = speed < 0 ? SPEED_INVALID : speed;
 160        lc->duplex = duplex < 0 ? DUPLEX_INVALID : duplex;
 161        if (!(lc->requested_fc & PAUSE_AUTONEG))
 162                fc = lc->requested_fc & (PAUSE_RX | PAUSE_TX);
 163
 164        if (link_ok && speed >= 0 && lc->autoneg == AUTONEG_ENABLE) {
 165                /* Set MAC speed, duplex, and flow control to match PHY. */
 166                struct cmac *mac = adapter->port[port_id].mac;
 167
 168                mac->ops->set_speed_duplex_fc(mac, speed, duplex, fc);
 169                lc->fc = (unsigned char)fc;
 170        }
 171        t1_link_negotiated(adapter, port_id, link_ok, speed, duplex, fc);
 172}
 173
 174static int t1_pci_intr_handler(adapter_t *adapter)
 175{
 176        u32 pcix_cause;
 177
 178        pci_read_config_dword(adapter->pdev, A_PCICFG_INTR_CAUSE, &pcix_cause);
 179
 180        if (pcix_cause) {
 181                pci_write_config_dword(adapter->pdev, A_PCICFG_INTR_CAUSE,
 182                                       pcix_cause);
 183                t1_fatal_err(adapter);    /* PCI errors are fatal */
 184        }
 185        return 0;
 186}
 187
 188#ifdef CONFIG_CHELSIO_T1_1G
 189#include "fpga_defs.h"
 190
 191/*
 192 * PHY interrupt handler for FPGA boards.
 193 */
 194static int fpga_phy_intr_handler(adapter_t *adapter)
 195{
 196        int p;
 197        u32 cause = readl(adapter->regs + FPGA_GMAC_ADDR_INTERRUPT_CAUSE);
 198
 199        for_each_port(adapter, p)
 200                if (cause & (1 << p)) {
 201                        struct cphy *phy = adapter->port[p].phy;
 202                        int phy_cause = phy->ops->interrupt_handler(phy);
 203
 204                        if (phy_cause & cphy_cause_link_change)
 205                                t1_link_changed(adapter, p);
 206                }
 207        writel(cause, adapter->regs + FPGA_GMAC_ADDR_INTERRUPT_CAUSE);
 208        return 0;
 209}
 210
 211/*
 212 * Slow path interrupt handler for FPGAs.
 213 */
 214static int fpga_slow_intr(adapter_t *adapter)
 215{
 216        u32 cause = readl(adapter->regs + A_PL_CAUSE);
 217
 218        cause &= ~F_PL_INTR_SGE_DATA;
 219        if (cause & F_PL_INTR_SGE_ERR)
 220                t1_sge_intr_error_handler(adapter->sge);
 221
 222        if (cause & FPGA_PCIX_INTERRUPT_GMAC)
 223                fpga_phy_intr_handler(adapter);
 224
 225        if (cause & FPGA_PCIX_INTERRUPT_TP) {
 226                /*
 227                 * FPGA doesn't support MC4 interrupts and it requires
 228                 * this odd layer of indirection for MC5.
 229                 */
 230                u32 tp_cause = readl(adapter->regs + FPGA_TP_ADDR_INTERRUPT_CAUSE);
 231
 232                /* Clear TP interrupt */
 233                writel(tp_cause, adapter->regs + FPGA_TP_ADDR_INTERRUPT_CAUSE);
 234        }
 235        if (cause & FPGA_PCIX_INTERRUPT_PCIX)
 236                t1_pci_intr_handler(adapter);
 237
 238        /* Clear the interrupts just processed. */
 239        if (cause)
 240                writel(cause, adapter->regs + A_PL_CAUSE);
 241
 242        return cause != 0;
 243}
 244#endif
 245
 246/*
 247 * Wait until Elmer's MI1 interface is ready for new operations.
 248 */
 249static int mi1_wait_until_ready(adapter_t *adapter, int mi1_reg)
 250{
 251        int attempts = 100, busy;
 252
 253        do {
 254                u32 val;
 255
 256                __t1_tpi_read(adapter, mi1_reg, &val);
 257                busy = val & F_MI1_OP_BUSY;
 258                if (busy)
 259                        udelay(10);
 260        } while (busy && --attempts);
 261        if (busy)
 262                pr_alert("%s: MDIO operation timed out\n", adapter->name);
 263        return busy;
 264}
 265
 266/*
 267 * MI1 MDIO initialization.
 268 */
 269static void mi1_mdio_init(adapter_t *adapter, const struct board_info *bi)
 270{
 271        u32 clkdiv = bi->clock_elmer0 / (2 * bi->mdio_mdc) - 1;
 272        u32 val = F_MI1_PREAMBLE_ENABLE | V_MI1_MDI_INVERT(bi->mdio_mdiinv) |
 273                V_MI1_MDI_ENABLE(bi->mdio_mdien) | V_MI1_CLK_DIV(clkdiv);
 274
 275        if (!(bi->caps & SUPPORTED_10000baseT_Full))
 276                val |= V_MI1_SOF(1);
 277        t1_tpi_write(adapter, A_ELMER0_PORT0_MI1_CFG, val);
 278}
 279
 280#if defined(CONFIG_CHELSIO_T1_1G)
 281/*
 282 * Elmer MI1 MDIO read/write operations.
 283 */
 284static int mi1_mdio_read(struct net_device *dev, int phy_addr, int mmd_addr,
 285                         u16 reg_addr)
 286{
 287        struct adapter *adapter = dev->ml_priv;
 288        u32 addr = V_MI1_REG_ADDR(reg_addr) | V_MI1_PHY_ADDR(phy_addr);
 289        unsigned int val;
 290
 291        spin_lock(&adapter->tpi_lock);
 292        __t1_tpi_write(adapter, A_ELMER0_PORT0_MI1_ADDR, addr);
 293        __t1_tpi_write(adapter,
 294                        A_ELMER0_PORT0_MI1_OP, MI1_OP_DIRECT_READ);
 295        mi1_wait_until_ready(adapter, A_ELMER0_PORT0_MI1_OP);
 296        __t1_tpi_read(adapter, A_ELMER0_PORT0_MI1_DATA, &val);
 297        spin_unlock(&adapter->tpi_lock);
 298        return val;
 299}
 300
 301static int mi1_mdio_write(struct net_device *dev, int phy_addr, int mmd_addr,
 302                          u16 reg_addr, u16 val)
 303{
 304        struct adapter *adapter = dev->ml_priv;
 305        u32 addr = V_MI1_REG_ADDR(reg_addr) | V_MI1_PHY_ADDR(phy_addr);
 306
 307        spin_lock(&adapter->tpi_lock);
 308        __t1_tpi_write(adapter, A_ELMER0_PORT0_MI1_ADDR, addr);
 309        __t1_tpi_write(adapter, A_ELMER0_PORT0_MI1_DATA, val);
 310        __t1_tpi_write(adapter,
 311                        A_ELMER0_PORT0_MI1_OP, MI1_OP_DIRECT_WRITE);
 312        mi1_wait_until_ready(adapter, A_ELMER0_PORT0_MI1_OP);
 313        spin_unlock(&adapter->tpi_lock);
 314        return 0;
 315}
 316
 317static const struct mdio_ops mi1_mdio_ops = {
 318        .init = mi1_mdio_init,
 319        .read = mi1_mdio_read,
 320        .write = mi1_mdio_write,
 321        .mode_support = MDIO_SUPPORTS_C22
 322};
 323
 324#endif
 325
 326static int mi1_mdio_ext_read(struct net_device *dev, int phy_addr, int mmd_addr,
 327                             u16 reg_addr)
 328{
 329        struct adapter *adapter = dev->ml_priv;
 330        u32 addr = V_MI1_REG_ADDR(mmd_addr) | V_MI1_PHY_ADDR(phy_addr);
 331        unsigned int val;
 332
 333        spin_lock(&adapter->tpi_lock);
 334
 335        /* Write the address we want. */
 336        __t1_tpi_write(adapter, A_ELMER0_PORT0_MI1_ADDR, addr);
 337        __t1_tpi_write(adapter, A_ELMER0_PORT0_MI1_DATA, reg_addr);
 338        __t1_tpi_write(adapter, A_ELMER0_PORT0_MI1_OP,
 339                       MI1_OP_INDIRECT_ADDRESS);
 340        mi1_wait_until_ready(adapter, A_ELMER0_PORT0_MI1_OP);
 341
 342        /* Write the operation we want. */
 343        __t1_tpi_write(adapter,
 344                        A_ELMER0_PORT0_MI1_OP, MI1_OP_INDIRECT_READ);
 345        mi1_wait_until_ready(adapter, A_ELMER0_PORT0_MI1_OP);
 346
 347        /* Read the data. */
 348        __t1_tpi_read(adapter, A_ELMER0_PORT0_MI1_DATA, &val);
 349        spin_unlock(&adapter->tpi_lock);
 350        return val;
 351}
 352
 353static int mi1_mdio_ext_write(struct net_device *dev, int phy_addr,
 354                              int mmd_addr, u16 reg_addr, u16 val)
 355{
 356        struct adapter *adapter = dev->ml_priv;
 357        u32 addr = V_MI1_REG_ADDR(mmd_addr) | V_MI1_PHY_ADDR(phy_addr);
 358
 359        spin_lock(&adapter->tpi_lock);
 360
 361        /* Write the address we want. */
 362        __t1_tpi_write(adapter, A_ELMER0_PORT0_MI1_ADDR, addr);
 363        __t1_tpi_write(adapter, A_ELMER0_PORT0_MI1_DATA, reg_addr);
 364        __t1_tpi_write(adapter, A_ELMER0_PORT0_MI1_OP,
 365                       MI1_OP_INDIRECT_ADDRESS);
 366        mi1_wait_until_ready(adapter, A_ELMER0_PORT0_MI1_OP);
 367
 368        /* Write the data. */
 369        __t1_tpi_write(adapter, A_ELMER0_PORT0_MI1_DATA, val);
 370        __t1_tpi_write(adapter, A_ELMER0_PORT0_MI1_OP, MI1_OP_INDIRECT_WRITE);
 371        mi1_wait_until_ready(adapter, A_ELMER0_PORT0_MI1_OP);
 372        spin_unlock(&adapter->tpi_lock);
 373        return 0;
 374}
 375
 376static const struct mdio_ops mi1_mdio_ext_ops = {
 377        .init = mi1_mdio_init,
 378        .read = mi1_mdio_ext_read,
 379        .write = mi1_mdio_ext_write,
 380        .mode_support = MDIO_SUPPORTS_C45 | MDIO_EMULATE_C22
 381};
 382
 383enum {
 384        CH_BRD_T110_1CU,
 385        CH_BRD_N110_1F,
 386        CH_BRD_N210_1F,
 387        CH_BRD_T210_1F,
 388        CH_BRD_T210_1CU,
 389        CH_BRD_N204_4CU,
 390};
 391
 392static const struct board_info t1_board[] = {
 393        {
 394                .board          = CHBT_BOARD_CHT110,
 395                .port_number    = 1,
 396                .caps           = SUPPORTED_10000baseT_Full,
 397                .chip_term      = CHBT_TERM_T1,
 398                .chip_mac       = CHBT_MAC_PM3393,
 399                .chip_phy       = CHBT_PHY_MY3126,
 400                .clock_core     = 125000000,
 401                .clock_mc3      = 150000000,
 402                .clock_mc4      = 125000000,
 403                .espi_nports    = 1,
 404                .clock_elmer0   = 44,
 405                .mdio_mdien     = 1,
 406                .mdio_mdiinv    = 1,
 407                .mdio_mdc       = 1,
 408                .mdio_phybaseaddr = 1,
 409                .gmac           = &t1_pm3393_ops,
 410                .gphy           = &t1_my3126_ops,
 411                .mdio_ops       = &mi1_mdio_ext_ops,
 412                .desc           = "Chelsio T110 1x10GBase-CX4 TOE",
 413        },
 414
 415        {
 416                .board          = CHBT_BOARD_N110,
 417                .port_number    = 1,
 418                .caps           = SUPPORTED_10000baseT_Full | SUPPORTED_FIBRE,
 419                .chip_term      = CHBT_TERM_T1,
 420                .chip_mac       = CHBT_MAC_PM3393,
 421                .chip_phy       = CHBT_PHY_88X2010,
 422                .clock_core     = 125000000,
 423                .espi_nports    = 1,
 424                .clock_elmer0   = 44,
 425                .mdio_mdien     = 0,
 426                .mdio_mdiinv    = 0,
 427                .mdio_mdc       = 1,
 428                .mdio_phybaseaddr = 0,
 429                .gmac           = &t1_pm3393_ops,
 430                .gphy           = &t1_mv88x201x_ops,
 431                .mdio_ops       = &mi1_mdio_ext_ops,
 432                .desc           = "Chelsio N110 1x10GBaseX NIC",
 433        },
 434
 435        {
 436                .board          = CHBT_BOARD_N210,
 437                .port_number    = 1,
 438                .caps           = SUPPORTED_10000baseT_Full | SUPPORTED_FIBRE,
 439                .chip_term      = CHBT_TERM_T2,
 440                .chip_mac       = CHBT_MAC_PM3393,
 441                .chip_phy       = CHBT_PHY_88X2010,
 442                .clock_core     = 125000000,
 443                .espi_nports    = 1,
 444                .clock_elmer0   = 44,
 445                .mdio_mdien     = 0,
 446                .mdio_mdiinv    = 0,
 447                .mdio_mdc       = 1,
 448                .mdio_phybaseaddr = 0,
 449                .gmac           = &t1_pm3393_ops,
 450                .gphy           = &t1_mv88x201x_ops,
 451                .mdio_ops       = &mi1_mdio_ext_ops,
 452                .desc           = "Chelsio N210 1x10GBaseX NIC",
 453        },
 454
 455        {
 456                .board          = CHBT_BOARD_CHT210,
 457                .port_number    = 1,
 458                .caps           = SUPPORTED_10000baseT_Full,
 459                .chip_term      = CHBT_TERM_T2,
 460                .chip_mac       = CHBT_MAC_PM3393,
 461                .chip_phy       = CHBT_PHY_88X2010,
 462                .clock_core     = 125000000,
 463                .clock_mc3      = 133000000,
 464                .clock_mc4      = 125000000,
 465                .espi_nports    = 1,
 466                .clock_elmer0   = 44,
 467                .mdio_mdien     = 0,
 468                .mdio_mdiinv    = 0,
 469                .mdio_mdc       = 1,
 470                .mdio_phybaseaddr = 0,
 471                .gmac           = &t1_pm3393_ops,
 472                .gphy           = &t1_mv88x201x_ops,
 473                .mdio_ops       = &mi1_mdio_ext_ops,
 474                .desc           = "Chelsio T210 1x10GBaseX TOE",
 475        },
 476
 477        {
 478                .board          = CHBT_BOARD_CHT210,
 479                .port_number    = 1,
 480                .caps           = SUPPORTED_10000baseT_Full,
 481                .chip_term      = CHBT_TERM_T2,
 482                .chip_mac       = CHBT_MAC_PM3393,
 483                .chip_phy       = CHBT_PHY_MY3126,
 484                .clock_core     = 125000000,
 485                .clock_mc3      = 133000000,
 486                .clock_mc4      = 125000000,
 487                .espi_nports    = 1,
 488                .clock_elmer0   = 44,
 489                .mdio_mdien     = 1,
 490                .mdio_mdiinv    = 1,
 491                .mdio_mdc       = 1,
 492                .mdio_phybaseaddr = 1,
 493                .gmac           = &t1_pm3393_ops,
 494                .gphy           = &t1_my3126_ops,
 495                .mdio_ops       = &mi1_mdio_ext_ops,
 496                .desc           = "Chelsio T210 1x10GBase-CX4 TOE",
 497        },
 498
 499#ifdef CONFIG_CHELSIO_T1_1G
 500        {
 501                .board          = CHBT_BOARD_CHN204,
 502                .port_number    = 4,
 503                .caps           = SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full
 504                                | SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full
 505                                | SUPPORTED_1000baseT_Full | SUPPORTED_Autoneg |
 506                                  SUPPORTED_PAUSE | SUPPORTED_TP,
 507                .chip_term      = CHBT_TERM_T2,
 508                .chip_mac       = CHBT_MAC_VSC7321,
 509                .chip_phy       = CHBT_PHY_88E1111,
 510                .clock_core     = 100000000,
 511                .espi_nports    = 4,
 512                .clock_elmer0   = 44,
 513                .mdio_mdien     = 0,
 514                .mdio_mdiinv    = 0,
 515                .mdio_mdc       = 0,
 516                .mdio_phybaseaddr = 4,
 517                .gmac           = &t1_vsc7326_ops,
 518                .gphy           = &t1_mv88e1xxx_ops,
 519                .mdio_ops       = &mi1_mdio_ops,
 520                .desc           = "Chelsio N204 4x100/1000BaseT NIC",
 521        },
 522#endif
 523
 524};
 525
 526DEFINE_PCI_DEVICE_TABLE(t1_pci_tbl) = {
 527        CH_DEVICE(8, 0, CH_BRD_T110_1CU),
 528        CH_DEVICE(8, 1, CH_BRD_T110_1CU),
 529        CH_DEVICE(7, 0, CH_BRD_N110_1F),
 530        CH_DEVICE(10, 1, CH_BRD_N210_1F),
 531        CH_DEVICE(11, 1, CH_BRD_T210_1F),
 532        CH_DEVICE(14, 1, CH_BRD_T210_1CU),
 533        CH_DEVICE(16, 1, CH_BRD_N204_4CU),
 534        { 0 }
 535};
 536
 537MODULE_DEVICE_TABLE(pci, t1_pci_tbl);
 538
 539/*
 540 * Return the board_info structure with a given index.  Out-of-range indices
 541 * return NULL.
 542 */
 543const struct board_info *t1_get_board_info(unsigned int board_id)
 544{
 545        return board_id < ARRAY_SIZE(t1_board) ? &t1_board[board_id] : NULL;
 546}
 547
 548struct chelsio_vpd_t {
 549        u32 format_version;
 550        u8 serial_number[16];
 551        u8 mac_base_address[6];
 552        u8 pad[2];           /* make multiple-of-4 size requirement explicit */
 553};
 554
 555#define EEPROMSIZE        (8 * 1024)
 556#define EEPROM_MAX_POLL   4
 557
 558/*
 559 * Read SEEPROM. A zero is written to the flag register when the address is
 560 * written to the Control register. The hardware device will set the flag to a
 561 * one when 4B have been transferred to the Data register.
 562 */
 563int t1_seeprom_read(adapter_t *adapter, u32 addr, __le32 *data)
 564{
 565        int i = EEPROM_MAX_POLL;
 566        u16 val;
 567        u32 v;
 568
 569        if (addr >= EEPROMSIZE || (addr & 3))
 570                return -EINVAL;
 571
 572        pci_write_config_word(adapter->pdev, A_PCICFG_VPD_ADDR, (u16)addr);
 573        do {
 574                udelay(50);
 575                pci_read_config_word(adapter->pdev, A_PCICFG_VPD_ADDR, &val);
 576        } while (!(val & F_VPD_OP_FLAG) && --i);
 577
 578        if (!(val & F_VPD_OP_FLAG)) {
 579                pr_err("%s: reading EEPROM address 0x%x failed\n",
 580                       adapter->name, addr);
 581                return -EIO;
 582        }
 583        pci_read_config_dword(adapter->pdev, A_PCICFG_VPD_DATA, &v);
 584        *data = cpu_to_le32(v);
 585        return 0;
 586}
 587
 588static int t1_eeprom_vpd_get(adapter_t *adapter, struct chelsio_vpd_t *vpd)
 589{
 590        int addr, ret = 0;
 591
 592        for (addr = 0; !ret && addr < sizeof(*vpd); addr += sizeof(u32))
 593                ret = t1_seeprom_read(adapter, addr,
 594                                      (__le32 *)((u8 *)vpd + addr));
 595
 596        return ret;
 597}
 598
 599/*
 600 * Read a port's MAC address from the VPD ROM.
 601 */
 602static int vpd_macaddress_get(adapter_t *adapter, int index, u8 mac_addr[])
 603{
 604        struct chelsio_vpd_t vpd;
 605
 606        if (t1_eeprom_vpd_get(adapter, &vpd))
 607                return 1;
 608        memcpy(mac_addr, vpd.mac_base_address, 5);
 609        mac_addr[5] = vpd.mac_base_address[5] + index;
 610        return 0;
 611}
 612
 613/*
 614 * Set up the MAC/PHY according to the requested link settings.
 615 *
 616 * If the PHY can auto-negotiate first decide what to advertise, then
 617 * enable/disable auto-negotiation as desired and reset.
 618 *
 619 * If the PHY does not auto-negotiate we just reset it.
 620 *
 621 * If auto-negotiation is off set the MAC to the proper speed/duplex/FC,
 622 * otherwise do it later based on the outcome of auto-negotiation.
 623 */
 624int t1_link_start(struct cphy *phy, struct cmac *mac, struct link_config *lc)
 625{
 626        unsigned int fc = lc->requested_fc & (PAUSE_RX | PAUSE_TX);
 627
 628        if (lc->supported & SUPPORTED_Autoneg) {
 629                lc->advertising &= ~(ADVERTISED_ASYM_PAUSE | ADVERTISED_PAUSE);
 630                if (fc) {
 631                        if (fc == ((PAUSE_RX | PAUSE_TX) &
 632                                   (mac->adapter->params.nports < 2)))
 633                                lc->advertising |= ADVERTISED_PAUSE;
 634                        else {
 635                                lc->advertising |= ADVERTISED_ASYM_PAUSE;
 636                                if (fc == PAUSE_RX)
 637                                        lc->advertising |= ADVERTISED_PAUSE;
 638                        }
 639                }
 640                phy->ops->advertise(phy, lc->advertising);
 641
 642                if (lc->autoneg == AUTONEG_DISABLE) {
 643                        lc->speed = lc->requested_speed;
 644                        lc->duplex = lc->requested_duplex;
 645                        lc->fc = (unsigned char)fc;
 646                        mac->ops->set_speed_duplex_fc(mac, lc->speed,
 647                                                      lc->duplex, fc);
 648                        /* Also disables autoneg */
 649                        phy->state = PHY_AUTONEG_RDY;
 650                        phy->ops->set_speed_duplex(phy, lc->speed, lc->duplex);
 651                        phy->ops->reset(phy, 0);
 652                } else {
 653                        phy->state = PHY_AUTONEG_EN;
 654                        phy->ops->autoneg_enable(phy); /* also resets PHY */
 655                }
 656        } else {
 657                phy->state = PHY_AUTONEG_RDY;
 658                mac->ops->set_speed_duplex_fc(mac, -1, -1, fc);
 659                lc->fc = (unsigned char)fc;
 660                phy->ops->reset(phy, 0);
 661        }
 662        return 0;
 663}
 664
 665/*
 666 * External interrupt handler for boards using elmer0.
 667 */
 668int t1_elmer0_ext_intr_handler(adapter_t *adapter)
 669{
 670        struct cphy *phy;
 671        int phy_cause;
 672        u32 cause;
 673
 674        t1_tpi_read(adapter, A_ELMER0_INT_CAUSE, &cause);
 675
 676        switch (board_info(adapter)->board) {
 677#ifdef CONFIG_CHELSIO_T1_1G
 678        case CHBT_BOARD_CHT204:
 679        case CHBT_BOARD_CHT204E:
 680        case CHBT_BOARD_CHN204:
 681        case CHBT_BOARD_CHT204V: {
 682                int i, port_bit;
 683                for_each_port(adapter, i) {
 684                        port_bit = i + 1;
 685                        if (!(cause & (1 << port_bit)))
 686                                continue;
 687
 688                        phy = adapter->port[i].phy;
 689                        phy_cause = phy->ops->interrupt_handler(phy);
 690                        if (phy_cause & cphy_cause_link_change)
 691                                t1_link_changed(adapter, i);
 692                }
 693                break;
 694        }
 695        case CHBT_BOARD_CHT101:
 696                if (cause & ELMER0_GP_BIT1) { /* Marvell 88E1111 interrupt */
 697                        phy = adapter->port[0].phy;
 698                        phy_cause = phy->ops->interrupt_handler(phy);
 699                        if (phy_cause & cphy_cause_link_change)
 700                                t1_link_changed(adapter, 0);
 701                }
 702                break;
 703        case CHBT_BOARD_7500: {
 704                int p;
 705                /*
 706                 * Elmer0's interrupt cause isn't useful here because there is
 707                 * only one bit that can be set for all 4 ports.  This means
 708                 * we are forced to check every PHY's interrupt status
 709                 * register to see who initiated the interrupt.
 710                 */
 711                for_each_port(adapter, p) {
 712                        phy = adapter->port[p].phy;
 713                        phy_cause = phy->ops->interrupt_handler(phy);
 714                        if (phy_cause & cphy_cause_link_change)
 715                            t1_link_changed(adapter, p);
 716                }
 717                break;
 718        }
 719#endif
 720        case CHBT_BOARD_CHT210:
 721        case CHBT_BOARD_N210:
 722        case CHBT_BOARD_N110:
 723                if (cause & ELMER0_GP_BIT6) { /* Marvell 88x2010 interrupt */
 724                        phy = adapter->port[0].phy;
 725                        phy_cause = phy->ops->interrupt_handler(phy);
 726                        if (phy_cause & cphy_cause_link_change)
 727                                t1_link_changed(adapter, 0);
 728                }
 729                break;
 730        case CHBT_BOARD_8000:
 731        case CHBT_BOARD_CHT110:
 732                if (netif_msg_intr(adapter))
 733                        dev_dbg(&adapter->pdev->dev,
 734                                "External interrupt cause 0x%x\n", cause);
 735                if (cause & ELMER0_GP_BIT1) {        /* PMC3393 INTB */
 736                        struct cmac *mac = adapter->port[0].mac;
 737
 738                        mac->ops->interrupt_handler(mac);
 739                }
 740                if (cause & ELMER0_GP_BIT5) {        /* XPAK MOD_DETECT */
 741                        u32 mod_detect;
 742
 743                        t1_tpi_read(adapter,
 744                                        A_ELMER0_GPI_STAT, &mod_detect);
 745                        if (netif_msg_link(adapter))
 746                                dev_info(&adapter->pdev->dev, "XPAK %s\n",
 747                                         mod_detect ? "removed" : "inserted");
 748                }
 749                break;
 750        }
 751        t1_tpi_write(adapter, A_ELMER0_INT_CAUSE, cause);
 752        return 0;
 753}
 754
 755/* Enables all interrupts. */
 756void t1_interrupts_enable(adapter_t *adapter)
 757{
 758        unsigned int i;
 759
 760        adapter->slow_intr_mask = F_PL_INTR_SGE_ERR | F_PL_INTR_TP;
 761
 762        t1_sge_intr_enable(adapter->sge);
 763        t1_tp_intr_enable(adapter->tp);
 764        if (adapter->espi) {
 765                adapter->slow_intr_mask |= F_PL_INTR_ESPI;
 766                t1_espi_intr_enable(adapter->espi);
 767        }
 768
 769        /* Enable MAC/PHY interrupts for each port. */
 770        for_each_port(adapter, i) {
 771                adapter->port[i].mac->ops->interrupt_enable(adapter->port[i].mac);
 772                adapter->port[i].phy->ops->interrupt_enable(adapter->port[i].phy);
 773        }
 774
 775        /* Enable PCIX & external chip interrupts on ASIC boards. */
 776        if (t1_is_asic(adapter)) {
 777                u32 pl_intr = readl(adapter->regs + A_PL_ENABLE);
 778
 779                /* PCI-X interrupts */
 780                pci_write_config_dword(adapter->pdev, A_PCICFG_INTR_ENABLE,
 781                                       0xffffffff);
 782
 783                adapter->slow_intr_mask |= F_PL_INTR_EXT | F_PL_INTR_PCIX;
 784                pl_intr |= F_PL_INTR_EXT | F_PL_INTR_PCIX;
 785                writel(pl_intr, adapter->regs + A_PL_ENABLE);
 786        }
 787}
 788
 789/* Disables all interrupts. */
 790void t1_interrupts_disable(adapter_t* adapter)
 791{
 792        unsigned int i;
 793
 794        t1_sge_intr_disable(adapter->sge);
 795        t1_tp_intr_disable(adapter->tp);
 796        if (adapter->espi)
 797                t1_espi_intr_disable(adapter->espi);
 798
 799        /* Disable MAC/PHY interrupts for each port. */
 800        for_each_port(adapter, i) {
 801                adapter->port[i].mac->ops->interrupt_disable(adapter->port[i].mac);
 802                adapter->port[i].phy->ops->interrupt_disable(adapter->port[i].phy);
 803        }
 804
 805        /* Disable PCIX & external chip interrupts. */
 806        if (t1_is_asic(adapter))
 807                writel(0, adapter->regs + A_PL_ENABLE);
 808
 809        /* PCI-X interrupts */
 810        pci_write_config_dword(adapter->pdev, A_PCICFG_INTR_ENABLE, 0);
 811
 812        adapter->slow_intr_mask = 0;
 813}
 814
 815/* Clears all interrupts */
 816void t1_interrupts_clear(adapter_t* adapter)
 817{
 818        unsigned int i;
 819
 820        t1_sge_intr_clear(adapter->sge);
 821        t1_tp_intr_clear(adapter->tp);
 822        if (adapter->espi)
 823                t1_espi_intr_clear(adapter->espi);
 824
 825        /* Clear MAC/PHY interrupts for each port. */
 826        for_each_port(adapter, i) {
 827                adapter->port[i].mac->ops->interrupt_clear(adapter->port[i].mac);
 828                adapter->port[i].phy->ops->interrupt_clear(adapter->port[i].phy);
 829        }
 830
 831        /* Enable interrupts for external devices. */
 832        if (t1_is_asic(adapter)) {
 833                u32 pl_intr = readl(adapter->regs + A_PL_CAUSE);
 834
 835                writel(pl_intr | F_PL_INTR_EXT | F_PL_INTR_PCIX,
 836                       adapter->regs + A_PL_CAUSE);
 837        }
 838
 839        /* PCI-X interrupts */
 840        pci_write_config_dword(adapter->pdev, A_PCICFG_INTR_CAUSE, 0xffffffff);
 841}
 842
 843/*
 844 * Slow path interrupt handler for ASICs.
 845 */
 846static int asic_slow_intr(adapter_t *adapter)
 847{
 848        u32 cause = readl(adapter->regs + A_PL_CAUSE);
 849
 850        cause &= adapter->slow_intr_mask;
 851        if (!cause)
 852                return 0;
 853        if (cause & F_PL_INTR_SGE_ERR)
 854                t1_sge_intr_error_handler(adapter->sge);
 855        if (cause & F_PL_INTR_TP)
 856                t1_tp_intr_handler(adapter->tp);
 857        if (cause & F_PL_INTR_ESPI)
 858                t1_espi_intr_handler(adapter->espi);
 859        if (cause & F_PL_INTR_PCIX)
 860                t1_pci_intr_handler(adapter);
 861        if (cause & F_PL_INTR_EXT)
 862                t1_elmer0_ext_intr(adapter);
 863
 864        /* Clear the interrupts just processed. */
 865        writel(cause, adapter->regs + A_PL_CAUSE);
 866        readl(adapter->regs + A_PL_CAUSE); /* flush writes */
 867        return 1;
 868}
 869
 870int t1_slow_intr_handler(adapter_t *adapter)
 871{
 872#ifdef CONFIG_CHELSIO_T1_1G
 873        if (!t1_is_asic(adapter))
 874                return fpga_slow_intr(adapter);
 875#endif
 876        return asic_slow_intr(adapter);
 877}
 878
 879/* Power sequencing is a work-around for Intel's XPAKs. */
 880static void power_sequence_xpak(adapter_t* adapter)
 881{
 882        u32 mod_detect;
 883        u32 gpo;
 884
 885        /* Check for XPAK */
 886        t1_tpi_read(adapter, A_ELMER0_GPI_STAT, &mod_detect);
 887        if (!(ELMER0_GP_BIT5 & mod_detect)) {
 888                /* XPAK is present */
 889                t1_tpi_read(adapter, A_ELMER0_GPO, &gpo);
 890                gpo |= ELMER0_GP_BIT18;
 891                t1_tpi_write(adapter, A_ELMER0_GPO, gpo);
 892        }
 893}
 894
 895int __devinit t1_get_board_rev(adapter_t *adapter, const struct board_info *bi,
 896                               struct adapter_params *p)
 897{
 898        p->chip_version = bi->chip_term;
 899        p->is_asic = (p->chip_version != CHBT_TERM_FPGA);
 900        if (p->chip_version == CHBT_TERM_T1 ||
 901            p->chip_version == CHBT_TERM_T2 ||
 902            p->chip_version == CHBT_TERM_FPGA) {
 903                u32 val = readl(adapter->regs + A_TP_PC_CONFIG);
 904
 905                val = G_TP_PC_REV(val);
 906                if (val == 2)
 907                        p->chip_revision = TERM_T1B;
 908                else if (val == 3)
 909                        p->chip_revision = TERM_T2;
 910                else
 911                        return -1;
 912        } else
 913                return -1;
 914        return 0;
 915}
 916
 917/*
 918 * Enable board components other than the Chelsio chip, such as external MAC
 919 * and PHY.
 920 */
 921static int board_init(adapter_t *adapter, const struct board_info *bi)
 922{
 923        switch (bi->board) {
 924        case CHBT_BOARD_8000:
 925        case CHBT_BOARD_N110:
 926        case CHBT_BOARD_N210:
 927        case CHBT_BOARD_CHT210:
 928                t1_tpi_par(adapter, 0xf);
 929                t1_tpi_write(adapter, A_ELMER0_GPO, 0x800);
 930                break;
 931        case CHBT_BOARD_CHT110:
 932                t1_tpi_par(adapter, 0xf);
 933                t1_tpi_write(adapter, A_ELMER0_GPO, 0x1800);
 934
 935                /* TBD XXX Might not need.  This fixes a problem
 936                 *         described in the Intel SR XPAK errata.
 937                 */
 938                power_sequence_xpak(adapter);
 939                break;
 940#ifdef CONFIG_CHELSIO_T1_1G
 941        case CHBT_BOARD_CHT204E:
 942                /* add config space write here */
 943        case CHBT_BOARD_CHT204:
 944        case CHBT_BOARD_CHT204V:
 945        case CHBT_BOARD_CHN204:
 946                t1_tpi_par(adapter, 0xf);
 947                t1_tpi_write(adapter, A_ELMER0_GPO, 0x804);
 948                break;
 949        case CHBT_BOARD_CHT101:
 950        case CHBT_BOARD_7500:
 951                t1_tpi_par(adapter, 0xf);
 952                t1_tpi_write(adapter, A_ELMER0_GPO, 0x1804);
 953                break;
 954#endif
 955        }
 956        return 0;
 957}
 958
 959/*
 960 * Initialize and configure the Terminator HW modules.  Note that external
 961 * MAC and PHYs are initialized separately.
 962 */
 963int t1_init_hw_modules(adapter_t *adapter)
 964{
 965        int err = -EIO;
 966        const struct board_info *bi = board_info(adapter);
 967
 968        if (!bi->clock_mc4) {
 969                u32 val = readl(adapter->regs + A_MC4_CFG);
 970
 971                writel(val | F_READY | F_MC4_SLOW, adapter->regs + A_MC4_CFG);
 972                writel(F_M_BUS_ENABLE | F_TCAM_RESET,
 973                       adapter->regs + A_MC5_CONFIG);
 974        }
 975
 976        if (adapter->espi && t1_espi_init(adapter->espi, bi->chip_mac,
 977                                          bi->espi_nports))
 978                goto out_err;
 979
 980        if (t1_tp_reset(adapter->tp, &adapter->params.tp, bi->clock_core))
 981                goto out_err;
 982
 983        err = t1_sge_configure(adapter->sge, &adapter->params.sge);
 984        if (err)
 985                goto out_err;
 986
 987        err = 0;
 988out_err:
 989        return err;
 990}
 991
 992/*
 993 * Determine a card's PCI mode.
 994 */
 995static void __devinit get_pci_mode(adapter_t *adapter, struct chelsio_pci_params *p)
 996{
 997        static const unsigned short speed_map[] = { 33, 66, 100, 133 };
 998        u32 pci_mode;
 999
1000        pci_read_config_dword(adapter->pdev, A_PCICFG_MODE, &pci_mode);
1001        p->speed = speed_map[G_PCI_MODE_CLK(pci_mode)];
1002        p->width = (pci_mode & F_PCI_MODE_64BIT) ? 64 : 32;
1003        p->is_pcix = (pci_mode & F_PCI_MODE_PCIX) != 0;
1004}
1005
1006/*
1007 * Release the structures holding the SW per-Terminator-HW-module state.
1008 */
1009void t1_free_sw_modules(adapter_t *adapter)
1010{
1011        unsigned int i;
1012
1013        for_each_port(adapter, i) {
1014                struct cmac *mac = adapter->port[i].mac;
1015                struct cphy *phy = adapter->port[i].phy;
1016
1017                if (mac)
1018                        mac->ops->destroy(mac);
1019                if (phy)
1020                        phy->ops->destroy(phy);
1021        }
1022
1023        if (adapter->sge)
1024                t1_sge_destroy(adapter->sge);
1025        if (adapter->tp)
1026                t1_tp_destroy(adapter->tp);
1027        if (adapter->espi)
1028                t1_espi_destroy(adapter->espi);
1029}
1030
1031static void __devinit init_link_config(struct link_config *lc,
1032                                       const struct board_info *bi)
1033{
1034        lc->supported = bi->caps;
1035        lc->requested_speed = lc->speed = SPEED_INVALID;
1036        lc->requested_duplex = lc->duplex = DUPLEX_INVALID;
1037        lc->requested_fc = lc->fc = PAUSE_RX | PAUSE_TX;
1038        if (lc->supported & SUPPORTED_Autoneg) {
1039                lc->advertising = lc->supported;
1040                lc->autoneg = AUTONEG_ENABLE;
1041                lc->requested_fc |= PAUSE_AUTONEG;
1042        } else {
1043                lc->advertising = 0;
1044                lc->autoneg = AUTONEG_DISABLE;
1045        }
1046}
1047
1048/*
1049 * Allocate and initialize the data structures that hold the SW state of
1050 * the Terminator HW modules.
1051 */
1052int __devinit t1_init_sw_modules(adapter_t *adapter,
1053                                 const struct board_info *bi)
1054{
1055        unsigned int i;
1056
1057        adapter->params.brd_info = bi;
1058        adapter->params.nports = bi->port_number;
1059        adapter->params.stats_update_period = bi->gmac->stats_update_period;
1060
1061        adapter->sge = t1_sge_create(adapter, &adapter->params.sge);
1062        if (!adapter->sge) {
1063                pr_err("%s: SGE initialization failed\n",
1064                       adapter->name);
1065                goto error;
1066        }
1067
1068        if (bi->espi_nports && !(adapter->espi = t1_espi_create(adapter))) {
1069                pr_err("%s: ESPI initialization failed\n",
1070                       adapter->name);
1071                goto error;
1072        }
1073
1074        adapter->tp = t1_tp_create(adapter, &adapter->params.tp);
1075        if (!adapter->tp) {
1076                pr_err("%s: TP initialization failed\n",
1077                       adapter->name);
1078                goto error;
1079        }
1080
1081        board_init(adapter, bi);
1082        bi->mdio_ops->init(adapter, bi);
1083        if (bi->gphy->reset)
1084                bi->gphy->reset(adapter);
1085        if (bi->gmac->reset)
1086                bi->gmac->reset(adapter);
1087
1088        for_each_port(adapter, i) {
1089                u8 hw_addr[6];
1090                struct cmac *mac;
1091                int phy_addr = bi->mdio_phybaseaddr + i;
1092
1093                adapter->port[i].phy = bi->gphy->create(adapter->port[i].dev,
1094                                                        phy_addr, bi->mdio_ops);
1095                if (!adapter->port[i].phy) {
1096                        pr_err("%s: PHY %d initialization failed\n",
1097                               adapter->name, i);
1098                        goto error;
1099                }
1100
1101                adapter->port[i].mac = mac = bi->gmac->create(adapter, i);
1102                if (!mac) {
1103                        pr_err("%s: MAC %d initialization failed\n",
1104                               adapter->name, i);
1105                        goto error;
1106                }
1107
1108                /*
1109                 * Get the port's MAC addresses either from the EEPROM if one
1110                 * exists or the one hardcoded in the MAC.
1111                 */
1112                if (!t1_is_asic(adapter) || bi->chip_mac == CHBT_MAC_DUMMY)
1113                        mac->ops->macaddress_get(mac, hw_addr);
1114                else if (vpd_macaddress_get(adapter, i, hw_addr)) {
1115                        pr_err("%s: could not read MAC address from VPD ROM\n",
1116                               adapter->port[i].dev->name);
1117                        goto error;
1118                }
1119                memcpy(adapter->port[i].dev->dev_addr, hw_addr, ETH_ALEN);
1120                init_link_config(&adapter->port[i].link_config, bi);
1121        }
1122
1123        get_pci_mode(adapter, &adapter->params.pci);
1124        t1_interrupts_clear(adapter);
1125        return 0;
1126
1127error:
1128        t1_free_sw_modules(adapter);
1129        return -1;
1130}
1131