linux/drivers/net/atl1c/atl1c_hw.c
<<
>>
Prefs
   1/*
   2 * Copyright(c) 2007 Atheros Corporation. All rights reserved.
   3 *
   4 * Derived from Intel e1000 driver
   5 * Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved.
   6 *
   7 * This program is free software; you can redistribute it and/or modify it
   8 * under the terms of the GNU General Public License as published by the Free
   9 * Software Foundation; either version 2 of the License, or (at your option)
  10 * any later version.
  11 *
  12 * This program is distributed in the hope that it will be useful, but WITHOUT
  13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  14 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
  15 * more details.
  16 *
  17 * You should have received a copy of the GNU General Public License along with
  18 * this program; if not, write to the Free Software Foundation, Inc., 59
  19 * Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  20 */
  21#include <linux/pci.h>
  22#include <linux/delay.h>
  23#include <linux/mii.h>
  24#include <linux/crc32.h>
  25
  26#include "atl1c.h"
  27
  28/*
  29 * check_eeprom_exist
  30 * return 1 if eeprom exist
  31 */
  32int atl1c_check_eeprom_exist(struct atl1c_hw *hw)
  33{
  34        u32 data;
  35
  36        AT_READ_REG(hw, REG_TWSI_DEBUG, &data);
  37        if (data & TWSI_DEBUG_DEV_EXIST)
  38                return 1;
  39
  40        return 0;
  41}
  42
  43void atl1c_hw_set_mac_addr(struct atl1c_hw *hw)
  44{
  45        u32 value;
  46        /*
  47         * 00-0B-6A-F6-00-DC
  48         * 0:  6AF600DC 1: 000B
  49         * low dword
  50         */
  51        value = (((u32)hw->mac_addr[2]) << 24) |
  52                (((u32)hw->mac_addr[3]) << 16) |
  53                (((u32)hw->mac_addr[4]) << 8)  |
  54                (((u32)hw->mac_addr[5])) ;
  55        AT_WRITE_REG_ARRAY(hw, REG_MAC_STA_ADDR, 0, value);
  56        /* hight dword */
  57        value = (((u32)hw->mac_addr[0]) << 8) |
  58                (((u32)hw->mac_addr[1])) ;
  59        AT_WRITE_REG_ARRAY(hw, REG_MAC_STA_ADDR, 1, value);
  60}
  61
  62/*
  63 * atl1c_get_permanent_address
  64 * return 0 if get valid mac address,
  65 */
  66static int atl1c_get_permanent_address(struct atl1c_hw *hw)
  67{
  68        u32 addr[2];
  69        u32 i;
  70        u32 otp_ctrl_data;
  71        u32 twsi_ctrl_data;
  72        u8  eth_addr[ETH_ALEN];
  73
  74        /* init */
  75        addr[0] = addr[1] = 0;
  76        AT_READ_REG(hw, REG_OTP_CTRL, &otp_ctrl_data);
  77        if (atl1c_check_eeprom_exist(hw)) {
  78                /* Enable OTP CLK */
  79                if (!(otp_ctrl_data & OTP_CTRL_CLK_EN)) {
  80                        otp_ctrl_data |= OTP_CTRL_CLK_EN;
  81                        AT_WRITE_REG(hw, REG_OTP_CTRL, otp_ctrl_data);
  82                        AT_WRITE_FLUSH(hw);
  83                        msleep(1);
  84                }
  85
  86                AT_READ_REG(hw, REG_TWSI_CTRL, &twsi_ctrl_data);
  87                twsi_ctrl_data |= TWSI_CTRL_SW_LDSTART;
  88                AT_WRITE_REG(hw, REG_TWSI_CTRL, twsi_ctrl_data);
  89                for (i = 0; i < AT_TWSI_EEPROM_TIMEOUT; i++) {
  90                        msleep(10);
  91                        AT_READ_REG(hw, REG_TWSI_CTRL, &twsi_ctrl_data);
  92                        if ((twsi_ctrl_data & TWSI_CTRL_SW_LDSTART) == 0)
  93                                break;
  94                }
  95                if (i >= AT_TWSI_EEPROM_TIMEOUT)
  96                        return -1;
  97        }
  98        /* Disable OTP_CLK */
  99        if (otp_ctrl_data & OTP_CTRL_CLK_EN) {
 100                otp_ctrl_data &= ~OTP_CTRL_CLK_EN;
 101                AT_WRITE_REG(hw, REG_OTP_CTRL, otp_ctrl_data);
 102                AT_WRITE_FLUSH(hw);
 103                msleep(1);
 104        }
 105
 106        /* maybe MAC-address is from BIOS */
 107        AT_READ_REG(hw, REG_MAC_STA_ADDR, &addr[0]);
 108        AT_READ_REG(hw, REG_MAC_STA_ADDR + 4, &addr[1]);
 109        *(u32 *) &eth_addr[2] = swab32(addr[0]);
 110        *(u16 *) &eth_addr[0] = swab16(*(u16 *)&addr[1]);
 111
 112        if (is_valid_ether_addr(eth_addr)) {
 113                memcpy(hw->perm_mac_addr, eth_addr, ETH_ALEN);
 114                return 0;
 115        }
 116
 117        return -1;
 118}
 119
 120bool atl1c_read_eeprom(struct atl1c_hw *hw, u32 offset, u32 *p_value)
 121{
 122        int i;
 123        int ret = false;
 124        u32 otp_ctrl_data;
 125        u32 control;
 126        u32 data;
 127
 128        if (offset & 3)
 129                return ret; /* address do not align */
 130
 131        AT_READ_REG(hw, REG_OTP_CTRL, &otp_ctrl_data);
 132        if (!(otp_ctrl_data & OTP_CTRL_CLK_EN))
 133                AT_WRITE_REG(hw, REG_OTP_CTRL,
 134                                (otp_ctrl_data | OTP_CTRL_CLK_EN));
 135
 136        AT_WRITE_REG(hw, REG_EEPROM_DATA_LO, 0);
 137        control = (offset & EEPROM_CTRL_ADDR_MASK) << EEPROM_CTRL_ADDR_SHIFT;
 138        AT_WRITE_REG(hw, REG_EEPROM_CTRL, control);
 139
 140        for (i = 0; i < 10; i++) {
 141                udelay(100);
 142                AT_READ_REG(hw, REG_EEPROM_CTRL, &control);
 143                if (control & EEPROM_CTRL_RW)
 144                        break;
 145        }
 146        if (control & EEPROM_CTRL_RW) {
 147                AT_READ_REG(hw, REG_EEPROM_CTRL, &data);
 148                AT_READ_REG(hw, REG_EEPROM_DATA_LO, p_value);
 149                data = data & 0xFFFF;
 150                *p_value = swab32((data << 16) | (*p_value >> 16));
 151                ret = true;
 152        }
 153        if (!(otp_ctrl_data & OTP_CTRL_CLK_EN))
 154                AT_WRITE_REG(hw, REG_OTP_CTRL, otp_ctrl_data);
 155
 156        return ret;
 157}
 158/*
 159 * Reads the adapter's MAC address from the EEPROM
 160 *
 161 * hw - Struct containing variables accessed by shared code
 162 */
 163int atl1c_read_mac_addr(struct atl1c_hw *hw)
 164{
 165        int err = 0;
 166
 167        err = atl1c_get_permanent_address(hw);
 168        if (err)
 169                random_ether_addr(hw->perm_mac_addr);
 170
 171        memcpy(hw->mac_addr, hw->perm_mac_addr, sizeof(hw->perm_mac_addr));
 172        return 0;
 173}
 174
 175/*
 176 * atl1c_hash_mc_addr
 177 *  purpose
 178 *      set hash value for a multicast address
 179 *      hash calcu processing :
 180 *          1. calcu 32bit CRC for multicast address
 181 *          2. reverse crc with MSB to LSB
 182 */
 183u32 atl1c_hash_mc_addr(struct atl1c_hw *hw, u8 *mc_addr)
 184{
 185        u32 crc32;
 186        u32 value = 0;
 187        int i;
 188
 189        crc32 = ether_crc_le(6, mc_addr);
 190        for (i = 0; i < 32; i++)
 191                value |= (((crc32 >> i) & 1) << (31 - i));
 192
 193        return value;
 194}
 195
 196/*
 197 * Sets the bit in the multicast table corresponding to the hash value.
 198 * hw - Struct containing variables accessed by shared code
 199 * hash_value - Multicast address hash value
 200 */
 201void atl1c_hash_set(struct atl1c_hw *hw, u32 hash_value)
 202{
 203        u32 hash_bit, hash_reg;
 204        u32 mta;
 205
 206        /*
 207         * The HASH Table  is a register array of 2 32-bit registers.
 208         * It is treated like an array of 64 bits.  We want to set
 209         * bit BitArray[hash_value]. So we figure out what register
 210         * the bit is in, read it, OR in the new bit, then write
 211         * back the new value.  The register is determined by the
 212         * upper bit of the hash value and the bit within that
 213         * register are determined by the lower 5 bits of the value.
 214         */
 215        hash_reg = (hash_value >> 31) & 0x1;
 216        hash_bit = (hash_value >> 26) & 0x1F;
 217
 218        mta = AT_READ_REG_ARRAY(hw, REG_RX_HASH_TABLE, hash_reg);
 219
 220        mta |= (1 << hash_bit);
 221
 222        AT_WRITE_REG_ARRAY(hw, REG_RX_HASH_TABLE, hash_reg, mta);
 223}
 224
 225/*
 226 * Reads the value from a PHY register
 227 * hw - Struct containing variables accessed by shared code
 228 * reg_addr - address of the PHY register to read
 229 */
 230int atl1c_read_phy_reg(struct atl1c_hw *hw, u16 reg_addr, u16 *phy_data)
 231{
 232        u32 val;
 233        int i;
 234
 235        val = ((u32)(reg_addr & MDIO_REG_ADDR_MASK)) << MDIO_REG_ADDR_SHIFT |
 236                MDIO_START | MDIO_SUP_PREAMBLE | MDIO_RW |
 237                MDIO_CLK_25_4 << MDIO_CLK_SEL_SHIFT;
 238
 239        AT_WRITE_REG(hw, REG_MDIO_CTRL, val);
 240
 241        for (i = 0; i < MDIO_WAIT_TIMES; i++) {
 242                udelay(2);
 243                AT_READ_REG(hw, REG_MDIO_CTRL, &val);
 244                if (!(val & (MDIO_START | MDIO_BUSY)))
 245                        break;
 246        }
 247        if (!(val & (MDIO_START | MDIO_BUSY))) {
 248                *phy_data = (u16)val;
 249                return 0;
 250        }
 251
 252        return -1;
 253}
 254
 255/*
 256 * Writes a value to a PHY register
 257 * hw - Struct containing variables accessed by shared code
 258 * reg_addr - address of the PHY register to write
 259 * data - data to write to the PHY
 260 */
 261int atl1c_write_phy_reg(struct atl1c_hw *hw, u32 reg_addr, u16 phy_data)
 262{
 263        int i;
 264        u32 val;
 265
 266        val = ((u32)(phy_data & MDIO_DATA_MASK)) << MDIO_DATA_SHIFT   |
 267               (reg_addr & MDIO_REG_ADDR_MASK) << MDIO_REG_ADDR_SHIFT |
 268               MDIO_SUP_PREAMBLE | MDIO_START |
 269               MDIO_CLK_25_4 << MDIO_CLK_SEL_SHIFT;
 270
 271        AT_WRITE_REG(hw, REG_MDIO_CTRL, val);
 272
 273        for (i = 0; i < MDIO_WAIT_TIMES; i++) {
 274                udelay(2);
 275                AT_READ_REG(hw, REG_MDIO_CTRL, &val);
 276                if (!(val & (MDIO_START | MDIO_BUSY)))
 277                        break;
 278        }
 279
 280        if (!(val & (MDIO_START | MDIO_BUSY)))
 281                return 0;
 282
 283        return -1;
 284}
 285
 286/*
 287 * Configures PHY autoneg and flow control advertisement settings
 288 *
 289 * hw - Struct containing variables accessed by shared code
 290 */
 291static int atl1c_phy_setup_adv(struct atl1c_hw *hw)
 292{
 293        u16 mii_adv_data = ADVERTISE_DEFAULT_CAP & ~ADVERTISE_SPEED_MASK;
 294        u16 mii_giga_ctrl_data = GIGA_CR_1000T_DEFAULT_CAP &
 295                                ~GIGA_CR_1000T_SPEED_MASK;
 296
 297        if (hw->autoneg_advertised & ADVERTISED_10baseT_Half)
 298                mii_adv_data |= ADVERTISE_10HALF;
 299        if (hw->autoneg_advertised & ADVERTISED_10baseT_Full)
 300                mii_adv_data |= ADVERTISE_10FULL;
 301        if (hw->autoneg_advertised & ADVERTISED_100baseT_Half)
 302                mii_adv_data |= ADVERTISE_100HALF;
 303        if (hw->autoneg_advertised & ADVERTISED_100baseT_Full)
 304                mii_adv_data |= ADVERTISE_100FULL;
 305
 306        if (hw->autoneg_advertised & ADVERTISED_Autoneg)
 307                mii_adv_data |= ADVERTISE_10HALF  | ADVERTISE_10FULL |
 308                                ADVERTISE_100HALF | ADVERTISE_100FULL;
 309
 310        if (hw->ctrl_flags & ATL1C_LINK_CAP_1000M) {
 311                if (hw->autoneg_advertised & ADVERTISED_1000baseT_Half)
 312                        mii_giga_ctrl_data |= ADVERTISE_1000HALF;
 313                if (hw->autoneg_advertised & ADVERTISED_1000baseT_Full)
 314                        mii_giga_ctrl_data |= ADVERTISE_1000FULL;
 315                if (hw->autoneg_advertised & ADVERTISED_Autoneg)
 316                        mii_giga_ctrl_data |= ADVERTISE_1000HALF |
 317                                        ADVERTISE_1000FULL;
 318        }
 319
 320        if (atl1c_write_phy_reg(hw, MII_ADVERTISE, mii_adv_data) != 0 ||
 321            atl1c_write_phy_reg(hw, MII_GIGA_CR, mii_giga_ctrl_data) != 0)
 322                return -1;
 323        return 0;
 324}
 325
 326void atl1c_phy_disable(struct atl1c_hw *hw)
 327{
 328        AT_WRITE_REGW(hw, REG_GPHY_CTRL,
 329                        GPHY_CTRL_PW_WOL_DIS | GPHY_CTRL_EXT_RESET);
 330}
 331
 332static void atl1c_phy_magic_data(struct atl1c_hw *hw)
 333{
 334        u16 data;
 335
 336        data = ANA_LOOP_SEL_10BT | ANA_EN_MASK_TB | ANA_EN_10BT_IDLE |
 337                ((1 & ANA_INTERVAL_SEL_TIMER_MASK) <<
 338                ANA_INTERVAL_SEL_TIMER_SHIFT);
 339
 340        atl1c_write_phy_reg(hw, MII_DBG_ADDR, MII_ANA_CTRL_18);
 341        atl1c_write_phy_reg(hw, MII_DBG_DATA, data);
 342
 343        data = (2 & ANA_SERDES_CDR_BW_MASK) | ANA_MS_PAD_DBG |
 344                ANA_SERDES_EN_DEEM | ANA_SERDES_SEL_HSP | ANA_SERDES_EN_PLL |
 345                ANA_SERDES_EN_LCKDT;
 346
 347        atl1c_write_phy_reg(hw, MII_DBG_ADDR, MII_ANA_CTRL_5);
 348        atl1c_write_phy_reg(hw, MII_DBG_DATA, data);
 349
 350        data = (44 & ANA_LONG_CABLE_TH_100_MASK) |
 351                ((33 & ANA_SHORT_CABLE_TH_100_MASK) <<
 352                ANA_SHORT_CABLE_TH_100_SHIFT) | ANA_BP_BAD_LINK_ACCUM |
 353                ANA_BP_SMALL_BW;
 354
 355        atl1c_write_phy_reg(hw, MII_DBG_ADDR, MII_ANA_CTRL_54);
 356        atl1c_write_phy_reg(hw, MII_DBG_DATA, data);
 357
 358        data = (11 & ANA_IECHO_ADJ_MASK) | ((11 & ANA_IECHO_ADJ_MASK) <<
 359                ANA_IECHO_ADJ_2_SHIFT) | ((8 & ANA_IECHO_ADJ_MASK) <<
 360                ANA_IECHO_ADJ_1_SHIFT) | ((8 & ANA_IECHO_ADJ_MASK) <<
 361                ANA_IECHO_ADJ_0_SHIFT);
 362
 363        atl1c_write_phy_reg(hw, MII_DBG_ADDR, MII_ANA_CTRL_4);
 364        atl1c_write_phy_reg(hw, MII_DBG_DATA, data);
 365
 366        data = ANA_RESTART_CAL | ((7 & ANA_MANUL_SWICH_ON_MASK) <<
 367                ANA_MANUL_SWICH_ON_SHIFT) | ANA_MAN_ENABLE |
 368                ANA_SEL_HSP | ANA_EN_HB | ANA_OEN_125M;
 369
 370        atl1c_write_phy_reg(hw, MII_DBG_ADDR, MII_ANA_CTRL_0);
 371        atl1c_write_phy_reg(hw, MII_DBG_DATA, data);
 372
 373        if (hw->ctrl_flags & ATL1C_HIB_DISABLE) {
 374                atl1c_write_phy_reg(hw, MII_DBG_ADDR, MII_ANA_CTRL_41);
 375                if (atl1c_read_phy_reg(hw, MII_DBG_DATA, &data) != 0)
 376                        return;
 377                data &= ~ANA_TOP_PS_EN;
 378                atl1c_write_phy_reg(hw, MII_DBG_DATA, data);
 379
 380                atl1c_write_phy_reg(hw, MII_DBG_ADDR, MII_ANA_CTRL_11);
 381                if (atl1c_read_phy_reg(hw, MII_DBG_DATA, &data) != 0)
 382                        return;
 383                data &= ~ANA_PS_HIB_EN;
 384                atl1c_write_phy_reg(hw, MII_DBG_DATA, data);
 385        }
 386}
 387
 388int atl1c_phy_reset(struct atl1c_hw *hw)
 389{
 390        struct atl1c_adapter *adapter = hw->adapter;
 391        struct pci_dev *pdev = adapter->pdev;
 392        u32 phy_ctrl_data = GPHY_CTRL_DEFAULT;
 393        u32 mii_ier_data = IER_LINK_UP | IER_LINK_DOWN;
 394        int err;
 395
 396        if (hw->ctrl_flags & ATL1C_HIB_DISABLE)
 397                phy_ctrl_data &= ~GPHY_CTRL_HIB_EN;
 398
 399        AT_WRITE_REG(hw, REG_GPHY_CTRL, phy_ctrl_data);
 400        AT_WRITE_FLUSH(hw);
 401        msleep(40);
 402        phy_ctrl_data |= GPHY_CTRL_EXT_RESET;
 403        AT_WRITE_REG(hw, REG_GPHY_CTRL, phy_ctrl_data);
 404        AT_WRITE_FLUSH(hw);
 405        msleep(10);
 406
 407        /*Enable PHY LinkChange Interrupt */
 408        err = atl1c_write_phy_reg(hw, MII_IER, mii_ier_data);
 409        if (err) {
 410                if (netif_msg_hw(adapter))
 411                        dev_err(&pdev->dev,
 412                                "Error enable PHY linkChange Interrupt\n");
 413                return err;
 414        }
 415        if (!(hw->ctrl_flags & ATL1C_FPGA_VERSION))
 416                atl1c_phy_magic_data(hw);
 417        return 0;
 418}
 419
 420int atl1c_phy_init(struct atl1c_hw *hw)
 421{
 422        struct atl1c_adapter *adapter = (struct atl1c_adapter *)hw->adapter;
 423        struct pci_dev *pdev = adapter->pdev;
 424        int ret_val;
 425        u16 mii_bmcr_data = BMCR_RESET;
 426        u16 phy_id1, phy_id2;
 427
 428        if ((atl1c_read_phy_reg(hw, MII_PHYSID1, &phy_id1) != 0) ||
 429                (atl1c_read_phy_reg(hw, MII_PHYSID2, &phy_id2) != 0)) {
 430                        if (netif_msg_link(adapter))
 431                                dev_err(&pdev->dev, "Error get phy ID\n");
 432                return -1;
 433        }
 434        switch (hw->media_type) {
 435        case MEDIA_TYPE_AUTO_SENSOR:
 436                ret_val = atl1c_phy_setup_adv(hw);
 437                if (ret_val) {
 438                        if (netif_msg_link(adapter))
 439                                dev_err(&pdev->dev,
 440                                        "Error Setting up Auto-Negotiation\n");
 441                        return ret_val;
 442                }
 443                mii_bmcr_data |= BMCR_AUTO_NEG_EN | BMCR_RESTART_AUTO_NEG;
 444                break;
 445        case MEDIA_TYPE_100M_FULL:
 446                mii_bmcr_data |= BMCR_SPEED_100 | BMCR_FULL_DUPLEX;
 447                break;
 448        case MEDIA_TYPE_100M_HALF:
 449                mii_bmcr_data |= BMCR_SPEED_100;
 450                break;
 451        case MEDIA_TYPE_10M_FULL:
 452                mii_bmcr_data |= BMCR_SPEED_10 | BMCR_FULL_DUPLEX;
 453                break;
 454        case MEDIA_TYPE_10M_HALF:
 455                mii_bmcr_data |= BMCR_SPEED_10;
 456                break;
 457        default:
 458                if (netif_msg_link(adapter))
 459                        dev_err(&pdev->dev, "Wrong Media type %d\n",
 460                                hw->media_type);
 461                return -1;
 462                break;
 463        }
 464
 465        ret_val = atl1c_write_phy_reg(hw, MII_BMCR, mii_bmcr_data);
 466        if (ret_val)
 467                return ret_val;
 468        hw->phy_configured = true;
 469
 470        return 0;
 471}
 472
 473/*
 474 * Detects the current speed and duplex settings of the hardware.
 475 *
 476 * hw - Struct containing variables accessed by shared code
 477 * speed - Speed of the connection
 478 * duplex - Duplex setting of the connection
 479 */
 480int atl1c_get_speed_and_duplex(struct atl1c_hw *hw, u16 *speed, u16 *duplex)
 481{
 482        int err;
 483        u16 phy_data;
 484
 485        /* Read   PHY Specific Status Register (17) */
 486        err = atl1c_read_phy_reg(hw, MII_GIGA_PSSR, &phy_data);
 487        if (err)
 488                return err;
 489
 490        if (!(phy_data & GIGA_PSSR_SPD_DPLX_RESOLVED))
 491                return -1;
 492
 493        switch (phy_data & GIGA_PSSR_SPEED) {
 494        case GIGA_PSSR_1000MBS:
 495                *speed = SPEED_1000;
 496                break;
 497        case GIGA_PSSR_100MBS:
 498                *speed = SPEED_100;
 499                break;
 500        case  GIGA_PSSR_10MBS:
 501                *speed = SPEED_10;
 502                break;
 503        default:
 504                return -1;
 505                break;
 506        }
 507
 508        if (phy_data & GIGA_PSSR_DPLX)
 509                *duplex = FULL_DUPLEX;
 510        else
 511                *duplex = HALF_DUPLEX;
 512
 513        return 0;
 514}
 515
 516int atl1c_restart_autoneg(struct atl1c_hw *hw)
 517{
 518        int err = 0;
 519        u16 mii_bmcr_data = BMCR_RESET;
 520
 521        err = atl1c_phy_setup_adv(hw);
 522        if (err)
 523                return err;
 524        mii_bmcr_data |= BMCR_AUTO_NEG_EN | BMCR_RESTART_AUTO_NEG;
 525
 526        return atl1c_write_phy_reg(hw, MII_BMCR, mii_bmcr_data);
 527}
 528
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.