18cfa0ad2SJack F Vogel /****************************************************************************** 28cfa0ad2SJack F Vogel 3a69ed8dfSJack F Vogel Copyright (c) 2001-2010, Intel Corporation 48cfa0ad2SJack F Vogel All rights reserved. 58cfa0ad2SJack F Vogel 68cfa0ad2SJack F Vogel Redistribution and use in source and binary forms, with or without 78cfa0ad2SJack F Vogel modification, are permitted provided that the following conditions are met: 88cfa0ad2SJack F Vogel 98cfa0ad2SJack F Vogel 1. Redistributions of source code must retain the above copyright notice, 108cfa0ad2SJack F Vogel this list of conditions and the following disclaimer. 118cfa0ad2SJack F Vogel 128cfa0ad2SJack F Vogel 2. Redistributions in binary form must reproduce the above copyright 138cfa0ad2SJack F Vogel notice, this list of conditions and the following disclaimer in the 148cfa0ad2SJack F Vogel documentation and/or other materials provided with the distribution. 158cfa0ad2SJack F Vogel 168cfa0ad2SJack F Vogel 3. Neither the name of the Intel Corporation nor the names of its 178cfa0ad2SJack F Vogel contributors may be used to endorse or promote products derived from 188cfa0ad2SJack F Vogel this software without specific prior written permission. 198cfa0ad2SJack F Vogel 208cfa0ad2SJack F Vogel THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 218cfa0ad2SJack F Vogel AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 228cfa0ad2SJack F Vogel IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 238cfa0ad2SJack F Vogel ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 248cfa0ad2SJack F Vogel LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 258cfa0ad2SJack F Vogel CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 268cfa0ad2SJack F Vogel SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 278cfa0ad2SJack F Vogel INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 288cfa0ad2SJack F Vogel CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 298cfa0ad2SJack F Vogel ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 308cfa0ad2SJack F Vogel POSSIBILITY OF SUCH DAMAGE. 318cfa0ad2SJack F Vogel 328cfa0ad2SJack F Vogel ******************************************************************************/ 338cfa0ad2SJack F Vogel /*$FreeBSD$*/ 348cfa0ad2SJack F Vogel 35daf9197cSJack F Vogel /* 36daf9197cSJack F Vogel * 82562G 10/100 Network Connection 37daf9197cSJack F Vogel * 82562G-2 10/100 Network Connection 38daf9197cSJack F Vogel * 82562GT 10/100 Network Connection 39daf9197cSJack F Vogel * 82562GT-2 10/100 Network Connection 40daf9197cSJack F Vogel * 82562V 10/100 Network Connection 41daf9197cSJack F Vogel * 82562V-2 10/100 Network Connection 42daf9197cSJack F Vogel * 82566DC-2 Gigabit Network Connection 43daf9197cSJack F Vogel * 82566DC Gigabit Network Connection 44daf9197cSJack F Vogel * 82566DM-2 Gigabit Network Connection 45daf9197cSJack F Vogel * 82566DM Gigabit Network Connection 46daf9197cSJack F Vogel * 82566MC Gigabit Network Connection 47daf9197cSJack F Vogel * 82566MM Gigabit Network Connection 48daf9197cSJack F Vogel * 82567LM Gigabit Network Connection 49daf9197cSJack F Vogel * 82567LF Gigabit Network Connection 50daf9197cSJack F Vogel * 82567V Gigabit Network Connection 51daf9197cSJack F Vogel * 82567LM-2 Gigabit Network Connection 52daf9197cSJack F Vogel * 82567LF-2 Gigabit Network Connection 53daf9197cSJack F Vogel * 82567V-2 Gigabit Network Connection 54daf9197cSJack F Vogel * 82567LF-3 Gigabit Network Connection 55daf9197cSJack F Vogel * 82567LM-3 Gigabit Network Connection 56daf9197cSJack F Vogel * 82567LM-4 Gigabit Network Connection 579d81738fSJack F Vogel * 82577LM Gigabit Network Connection 589d81738fSJack F Vogel * 82577LC Gigabit Network Connection 599d81738fSJack F Vogel * 82578DM Gigabit Network Connection 609d81738fSJack F Vogel * 82578DC Gigabit Network Connection 618cfa0ad2SJack F Vogel */ 628cfa0ad2SJack F Vogel 638cfa0ad2SJack F Vogel #include "e1000_api.h" 648cfa0ad2SJack F Vogel 658cfa0ad2SJack F Vogel static s32 e1000_init_phy_params_ich8lan(struct e1000_hw *hw); 669d81738fSJack F Vogel static s32 e1000_init_phy_params_pchlan(struct e1000_hw *hw); 678cfa0ad2SJack F Vogel static s32 e1000_init_nvm_params_ich8lan(struct e1000_hw *hw); 688cfa0ad2SJack F Vogel static s32 e1000_init_mac_params_ich8lan(struct e1000_hw *hw); 698cfa0ad2SJack F Vogel static s32 e1000_acquire_swflag_ich8lan(struct e1000_hw *hw); 708cfa0ad2SJack F Vogel static void e1000_release_swflag_ich8lan(struct e1000_hw *hw); 714edd8523SJack F Vogel static s32 e1000_acquire_nvm_ich8lan(struct e1000_hw *hw); 724edd8523SJack F Vogel static void e1000_release_nvm_ich8lan(struct e1000_hw *hw); 738cfa0ad2SJack F Vogel static bool e1000_check_mng_mode_ich8lan(struct e1000_hw *hw); 748cfa0ad2SJack F Vogel static s32 e1000_check_reset_block_ich8lan(struct e1000_hw *hw); 758cfa0ad2SJack F Vogel static s32 e1000_phy_hw_reset_ich8lan(struct e1000_hw *hw); 764edd8523SJack F Vogel static s32 e1000_set_lplu_state_pchlan(struct e1000_hw *hw, bool active); 778cfa0ad2SJack F Vogel static s32 e1000_set_d0_lplu_state_ich8lan(struct e1000_hw *hw, 788cfa0ad2SJack F Vogel bool active); 798cfa0ad2SJack F Vogel static s32 e1000_set_d3_lplu_state_ich8lan(struct e1000_hw *hw, 808cfa0ad2SJack F Vogel bool active); 818cfa0ad2SJack F Vogel static s32 e1000_read_nvm_ich8lan(struct e1000_hw *hw, u16 offset, 828cfa0ad2SJack F Vogel u16 words, u16 *data); 838cfa0ad2SJack F Vogel static s32 e1000_write_nvm_ich8lan(struct e1000_hw *hw, u16 offset, 848cfa0ad2SJack F Vogel u16 words, u16 *data); 858cfa0ad2SJack F Vogel static s32 e1000_validate_nvm_checksum_ich8lan(struct e1000_hw *hw); 868cfa0ad2SJack F Vogel static s32 e1000_update_nvm_checksum_ich8lan(struct e1000_hw *hw); 878cfa0ad2SJack F Vogel static s32 e1000_valid_led_default_ich8lan(struct e1000_hw *hw, 888cfa0ad2SJack F Vogel u16 *data); 899d81738fSJack F Vogel static s32 e1000_id_led_init_pchlan(struct e1000_hw *hw); 908cfa0ad2SJack F Vogel static s32 e1000_get_bus_info_ich8lan(struct e1000_hw *hw); 918cfa0ad2SJack F Vogel static s32 e1000_reset_hw_ich8lan(struct e1000_hw *hw); 928cfa0ad2SJack F Vogel static s32 e1000_init_hw_ich8lan(struct e1000_hw *hw); 938cfa0ad2SJack F Vogel static s32 e1000_setup_link_ich8lan(struct e1000_hw *hw); 948cfa0ad2SJack F Vogel static s32 e1000_setup_copper_link_ich8lan(struct e1000_hw *hw); 958cfa0ad2SJack F Vogel static s32 e1000_get_link_up_info_ich8lan(struct e1000_hw *hw, 968cfa0ad2SJack F Vogel u16 *speed, u16 *duplex); 978cfa0ad2SJack F Vogel static s32 e1000_cleanup_led_ich8lan(struct e1000_hw *hw); 988cfa0ad2SJack F Vogel static s32 e1000_led_on_ich8lan(struct e1000_hw *hw); 998cfa0ad2SJack F Vogel static s32 e1000_led_off_ich8lan(struct e1000_hw *hw); 1004edd8523SJack F Vogel static s32 e1000_k1_gig_workaround_hv(struct e1000_hw *hw, bool link); 1019d81738fSJack F Vogel static s32 e1000_setup_led_pchlan(struct e1000_hw *hw); 1029d81738fSJack F Vogel static s32 e1000_cleanup_led_pchlan(struct e1000_hw *hw); 1039d81738fSJack F Vogel static s32 e1000_led_on_pchlan(struct e1000_hw *hw); 1049d81738fSJack F Vogel static s32 e1000_led_off_pchlan(struct e1000_hw *hw); 1058cfa0ad2SJack F Vogel static void e1000_clear_hw_cntrs_ich8lan(struct e1000_hw *hw); 1068cfa0ad2SJack F Vogel static s32 e1000_erase_flash_bank_ich8lan(struct e1000_hw *hw, u32 bank); 1078cfa0ad2SJack F Vogel static s32 e1000_flash_cycle_ich8lan(struct e1000_hw *hw, u32 timeout); 1088cfa0ad2SJack F Vogel static s32 e1000_flash_cycle_init_ich8lan(struct e1000_hw *hw); 1098cfa0ad2SJack F Vogel static void e1000_initialize_hw_bits_ich8lan(struct e1000_hw *hw); 1108cfa0ad2SJack F Vogel static s32 e1000_kmrn_lock_loss_workaround_ich8lan(struct e1000_hw *hw); 1118cfa0ad2SJack F Vogel static s32 e1000_read_flash_byte_ich8lan(struct e1000_hw *hw, 1128cfa0ad2SJack F Vogel u32 offset, u8 *data); 1138cfa0ad2SJack F Vogel static s32 e1000_read_flash_data_ich8lan(struct e1000_hw *hw, u32 offset, 1148cfa0ad2SJack F Vogel u8 size, u16 *data); 1158cfa0ad2SJack F Vogel static s32 e1000_read_flash_word_ich8lan(struct e1000_hw *hw, 1168cfa0ad2SJack F Vogel u32 offset, u16 *data); 1178cfa0ad2SJack F Vogel static s32 e1000_retry_write_flash_byte_ich8lan(struct e1000_hw *hw, 1188cfa0ad2SJack F Vogel u32 offset, u8 byte); 1198cfa0ad2SJack F Vogel static s32 e1000_write_flash_byte_ich8lan(struct e1000_hw *hw, 1208cfa0ad2SJack F Vogel u32 offset, u8 data); 1218cfa0ad2SJack F Vogel static s32 e1000_write_flash_data_ich8lan(struct e1000_hw *hw, u32 offset, 1228cfa0ad2SJack F Vogel u8 size, u16 data); 1238cfa0ad2SJack F Vogel static s32 e1000_get_cfg_done_ich8lan(struct e1000_hw *hw); 1248cfa0ad2SJack F Vogel static void e1000_power_down_phy_copper_ich8lan(struct e1000_hw *hw); 1254edd8523SJack F Vogel static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw); 1264edd8523SJack F Vogel static void e1000_lan_init_done_ich8lan(struct e1000_hw *hw); 1274edd8523SJack F Vogel static s32 e1000_sw_lcd_config_ich8lan(struct e1000_hw *hw); 128a69ed8dfSJack F Vogel static s32 e1000_set_mdio_slow_mode_hv(struct e1000_hw *hw); 1298cfa0ad2SJack F Vogel 1308cfa0ad2SJack F Vogel /* ICH GbE Flash Hardware Sequencing Flash Status Register bit breakdown */ 1318cfa0ad2SJack F Vogel /* Offset 04h HSFSTS */ 1328cfa0ad2SJack F Vogel union ich8_hws_flash_status { 1338cfa0ad2SJack F Vogel struct ich8_hsfsts { 1348cfa0ad2SJack F Vogel u16 flcdone :1; /* bit 0 Flash Cycle Done */ 1358cfa0ad2SJack F Vogel u16 flcerr :1; /* bit 1 Flash Cycle Error */ 1368cfa0ad2SJack F Vogel u16 dael :1; /* bit 2 Direct Access error Log */ 1378cfa0ad2SJack F Vogel u16 berasesz :2; /* bit 4:3 Sector Erase Size */ 1388cfa0ad2SJack F Vogel u16 flcinprog :1; /* bit 5 flash cycle in Progress */ 1398cfa0ad2SJack F Vogel u16 reserved1 :2; /* bit 13:6 Reserved */ 1408cfa0ad2SJack F Vogel u16 reserved2 :6; /* bit 13:6 Reserved */ 1418cfa0ad2SJack F Vogel u16 fldesvalid :1; /* bit 14 Flash Descriptor Valid */ 1428cfa0ad2SJack F Vogel u16 flockdn :1; /* bit 15 Flash Config Lock-Down */ 1438cfa0ad2SJack F Vogel } hsf_status; 1448cfa0ad2SJack F Vogel u16 regval; 1458cfa0ad2SJack F Vogel }; 1468cfa0ad2SJack F Vogel 1478cfa0ad2SJack F Vogel /* ICH GbE Flash Hardware Sequencing Flash control Register bit breakdown */ 1488cfa0ad2SJack F Vogel /* Offset 06h FLCTL */ 1498cfa0ad2SJack F Vogel union ich8_hws_flash_ctrl { 1508cfa0ad2SJack F Vogel struct ich8_hsflctl { 1518cfa0ad2SJack F Vogel u16 flcgo :1; /* 0 Flash Cycle Go */ 1528cfa0ad2SJack F Vogel u16 flcycle :2; /* 2:1 Flash Cycle */ 1538cfa0ad2SJack F Vogel u16 reserved :5; /* 7:3 Reserved */ 1548cfa0ad2SJack F Vogel u16 fldbcount :2; /* 9:8 Flash Data Byte Count */ 1558cfa0ad2SJack F Vogel u16 flockdn :6; /* 15:10 Reserved */ 1568cfa0ad2SJack F Vogel } hsf_ctrl; 1578cfa0ad2SJack F Vogel u16 regval; 1588cfa0ad2SJack F Vogel }; 1598cfa0ad2SJack F Vogel 1608cfa0ad2SJack F Vogel /* ICH Flash Region Access Permissions */ 1618cfa0ad2SJack F Vogel union ich8_hws_flash_regacc { 1628cfa0ad2SJack F Vogel struct ich8_flracc { 1638cfa0ad2SJack F Vogel u32 grra :8; /* 0:7 GbE region Read Access */ 1648cfa0ad2SJack F Vogel u32 grwa :8; /* 8:15 GbE region Write Access */ 1658cfa0ad2SJack F Vogel u32 gmrag :8; /* 23:16 GbE Master Read Access Grant */ 1668cfa0ad2SJack F Vogel u32 gmwag :8; /* 31:24 GbE Master Write Access Grant */ 1678cfa0ad2SJack F Vogel } hsf_flregacc; 1688cfa0ad2SJack F Vogel u16 regval; 1698cfa0ad2SJack F Vogel }; 1708cfa0ad2SJack F Vogel 1718cfa0ad2SJack F Vogel /** 1729d81738fSJack F Vogel * e1000_init_phy_params_pchlan - Initialize PHY function pointers 1739d81738fSJack F Vogel * @hw: pointer to the HW structure 1749d81738fSJack F Vogel * 1759d81738fSJack F Vogel * Initialize family-specific PHY parameters and function pointers. 1769d81738fSJack F Vogel **/ 1779d81738fSJack F Vogel static s32 e1000_init_phy_params_pchlan(struct e1000_hw *hw) 1789d81738fSJack F Vogel { 1799d81738fSJack F Vogel struct e1000_phy_info *phy = &hw->phy; 1808ec87fc5SJack F Vogel u32 ctrl; 1819d81738fSJack F Vogel s32 ret_val = E1000_SUCCESS; 1829d81738fSJack F Vogel 1839d81738fSJack F Vogel DEBUGFUNC("e1000_init_phy_params_pchlan"); 1849d81738fSJack F Vogel 1859d81738fSJack F Vogel phy->addr = 1; 1869d81738fSJack F Vogel phy->reset_delay_us = 100; 1879d81738fSJack F Vogel 1889d81738fSJack F Vogel phy->ops.acquire = e1000_acquire_swflag_ich8lan; 1899d81738fSJack F Vogel phy->ops.check_reset_block = e1000_check_reset_block_ich8lan; 1909d81738fSJack F Vogel phy->ops.get_cfg_done = e1000_get_cfg_done_ich8lan; 1919d81738fSJack F Vogel phy->ops.read_reg = e1000_read_phy_reg_hv; 1924edd8523SJack F Vogel phy->ops.read_reg_locked = e1000_read_phy_reg_hv_locked; 1939d81738fSJack F Vogel phy->ops.release = e1000_release_swflag_ich8lan; 1949d81738fSJack F Vogel phy->ops.reset = e1000_phy_hw_reset_ich8lan; 1954edd8523SJack F Vogel phy->ops.set_d0_lplu_state = e1000_set_lplu_state_pchlan; 1964edd8523SJack F Vogel phy->ops.set_d3_lplu_state = e1000_set_lplu_state_pchlan; 1979d81738fSJack F Vogel phy->ops.write_reg = e1000_write_phy_reg_hv; 1984edd8523SJack F Vogel phy->ops.write_reg_locked = e1000_write_phy_reg_hv_locked; 1999d81738fSJack F Vogel phy->ops.power_up = e1000_power_up_phy_copper; 2009d81738fSJack F Vogel phy->ops.power_down = e1000_power_down_phy_copper_ich8lan; 2019d81738fSJack F Vogel phy->autoneg_mask = AUTONEG_ADVERTISE_SPEED_DEFAULT; 2029d81738fSJack F Vogel 2038ec87fc5SJack F Vogel if ((hw->mac.type == e1000_pchlan) && 2048ec87fc5SJack F Vogel (!(E1000_READ_REG(hw, E1000_FWSM) & E1000_ICH_FWSM_FW_VALID))) { 2058ec87fc5SJack F Vogel 2068ec87fc5SJack F Vogel /* 2078ec87fc5SJack F Vogel * The MAC-PHY interconnect may still be in SMBus mode 2088ec87fc5SJack F Vogel * after Sx->S0. Toggle the LANPHYPC Value bit to force 2098ec87fc5SJack F Vogel * the interconnect to PCIe mode, but only if there is no 2108ec87fc5SJack F Vogel * firmware present otherwise firmware will have done it. 2118ec87fc5SJack F Vogel */ 2128ec87fc5SJack F Vogel ctrl = E1000_READ_REG(hw, E1000_CTRL); 2138ec87fc5SJack F Vogel ctrl |= E1000_CTRL_LANPHYPC_OVERRIDE; 2148ec87fc5SJack F Vogel ctrl &= ~E1000_CTRL_LANPHYPC_VALUE; 2158ec87fc5SJack F Vogel E1000_WRITE_REG(hw, E1000_CTRL, ctrl); 2168ec87fc5SJack F Vogel usec_delay(10); 2178ec87fc5SJack F Vogel ctrl &= ~E1000_CTRL_LANPHYPC_OVERRIDE; 2188ec87fc5SJack F Vogel E1000_WRITE_REG(hw, E1000_CTRL, ctrl); 2198ec87fc5SJack F Vogel msec_delay(50); 2208ec87fc5SJack F Vogel } 2218ec87fc5SJack F Vogel 2228ec87fc5SJack F Vogel /* 2238ec87fc5SJack F Vogel * Reset the PHY before any acccess to it. Doing so, ensures that 2248ec87fc5SJack F Vogel * the PHY is in a known good state before we read/write PHY registers. 2258ec87fc5SJack F Vogel * The generic reset is sufficient here, because we haven't determined 2268ec87fc5SJack F Vogel * the PHY type yet. 2278ec87fc5SJack F Vogel */ 2288ec87fc5SJack F Vogel ret_val = e1000_phy_hw_reset_generic(hw); 2298ec87fc5SJack F Vogel if (ret_val) 2308ec87fc5SJack F Vogel goto out; 2318ec87fc5SJack F Vogel 2329d81738fSJack F Vogel phy->id = e1000_phy_unknown; 233a69ed8dfSJack F Vogel ret_val = e1000_get_phy_id(hw); 234a69ed8dfSJack F Vogel if (ret_val) 235a69ed8dfSJack F Vogel goto out; 236a69ed8dfSJack F Vogel if ((phy->id == 0) || (phy->id == PHY_REVISION_MASK)) { 237a69ed8dfSJack F Vogel /* 238a69ed8dfSJack F Vogel * In case the PHY needs to be in mdio slow mode (eg. 82577), 239a69ed8dfSJack F Vogel * set slow mode and try to get the PHY id again. 240a69ed8dfSJack F Vogel */ 241a69ed8dfSJack F Vogel ret_val = e1000_set_mdio_slow_mode_hv(hw); 242a69ed8dfSJack F Vogel if (ret_val) 243a69ed8dfSJack F Vogel goto out; 244a69ed8dfSJack F Vogel ret_val = e1000_get_phy_id(hw); 245a69ed8dfSJack F Vogel if (ret_val) 246a69ed8dfSJack F Vogel goto out; 247a69ed8dfSJack F Vogel } 2489d81738fSJack F Vogel phy->type = e1000_get_phy_type_from_id(phy->id); 2499d81738fSJack F Vogel 2504edd8523SJack F Vogel switch (phy->type) { 2514edd8523SJack F Vogel case e1000_phy_82577: 2529d81738fSJack F Vogel phy->ops.check_polarity = e1000_check_polarity_82577; 2539d81738fSJack F Vogel phy->ops.force_speed_duplex = 2549d81738fSJack F Vogel e1000_phy_force_speed_duplex_82577; 2559d81738fSJack F Vogel phy->ops.get_cable_length = e1000_get_cable_length_82577; 2569d81738fSJack F Vogel phy->ops.get_info = e1000_get_phy_info_82577; 2579d81738fSJack F Vogel phy->ops.commit = e1000_phy_sw_reset_generic; 2588ec87fc5SJack F Vogel break; 2594edd8523SJack F Vogel case e1000_phy_82578: 2604edd8523SJack F Vogel phy->ops.check_polarity = e1000_check_polarity_m88; 2614edd8523SJack F Vogel phy->ops.force_speed_duplex = e1000_phy_force_speed_duplex_m88; 2624edd8523SJack F Vogel phy->ops.get_cable_length = e1000_get_cable_length_m88; 2634edd8523SJack F Vogel phy->ops.get_info = e1000_get_phy_info_m88; 2644edd8523SJack F Vogel break; 2654edd8523SJack F Vogel default: 2664edd8523SJack F Vogel ret_val = -E1000_ERR_PHY; 2674edd8523SJack F Vogel break; 2689d81738fSJack F Vogel } 2699d81738fSJack F Vogel 270a69ed8dfSJack F Vogel out: 2719d81738fSJack F Vogel return ret_val; 2729d81738fSJack F Vogel } 2739d81738fSJack F Vogel 2749d81738fSJack F Vogel /** 2758cfa0ad2SJack F Vogel * e1000_init_phy_params_ich8lan - Initialize PHY function pointers 2768cfa0ad2SJack F Vogel * @hw: pointer to the HW structure 2778cfa0ad2SJack F Vogel * 2788cfa0ad2SJack F Vogel * Initialize family-specific PHY parameters and function pointers. 2798cfa0ad2SJack F Vogel **/ 2808cfa0ad2SJack F Vogel static s32 e1000_init_phy_params_ich8lan(struct e1000_hw *hw) 2818cfa0ad2SJack F Vogel { 2828cfa0ad2SJack F Vogel struct e1000_phy_info *phy = &hw->phy; 2838cfa0ad2SJack F Vogel s32 ret_val = E1000_SUCCESS; 2848cfa0ad2SJack F Vogel u16 i = 0; 2858cfa0ad2SJack F Vogel 2868cfa0ad2SJack F Vogel DEBUGFUNC("e1000_init_phy_params_ich8lan"); 2878cfa0ad2SJack F Vogel 2888cfa0ad2SJack F Vogel phy->addr = 1; 2898cfa0ad2SJack F Vogel phy->reset_delay_us = 100; 2908cfa0ad2SJack F Vogel 2918cfa0ad2SJack F Vogel phy->ops.acquire = e1000_acquire_swflag_ich8lan; 2928cfa0ad2SJack F Vogel phy->ops.check_reset_block = e1000_check_reset_block_ich8lan; 2938cfa0ad2SJack F Vogel phy->ops.get_cable_length = e1000_get_cable_length_igp_2; 2948cfa0ad2SJack F Vogel phy->ops.get_cfg_done = e1000_get_cfg_done_ich8lan; 2958cfa0ad2SJack F Vogel phy->ops.read_reg = e1000_read_phy_reg_igp; 2968cfa0ad2SJack F Vogel phy->ops.release = e1000_release_swflag_ich8lan; 2978cfa0ad2SJack F Vogel phy->ops.reset = e1000_phy_hw_reset_ich8lan; 2988cfa0ad2SJack F Vogel phy->ops.set_d0_lplu_state = e1000_set_d0_lplu_state_ich8lan; 2998cfa0ad2SJack F Vogel phy->ops.set_d3_lplu_state = e1000_set_d3_lplu_state_ich8lan; 3008cfa0ad2SJack F Vogel phy->ops.write_reg = e1000_write_phy_reg_igp; 3018cfa0ad2SJack F Vogel phy->ops.power_up = e1000_power_up_phy_copper; 3028cfa0ad2SJack F Vogel phy->ops.power_down = e1000_power_down_phy_copper_ich8lan; 3038cfa0ad2SJack F Vogel 3048cfa0ad2SJack F Vogel /* 3058cfa0ad2SJack F Vogel * We may need to do this twice - once for IGP and if that fails, 3068cfa0ad2SJack F Vogel * we'll set BM func pointers and try again 3078cfa0ad2SJack F Vogel */ 3088cfa0ad2SJack F Vogel ret_val = e1000_determine_phy_address(hw); 3098cfa0ad2SJack F Vogel if (ret_val) { 3108cfa0ad2SJack F Vogel phy->ops.write_reg = e1000_write_phy_reg_bm; 3118cfa0ad2SJack F Vogel phy->ops.read_reg = e1000_read_phy_reg_bm; 3128cfa0ad2SJack F Vogel ret_val = e1000_determine_phy_address(hw); 3138cfa0ad2SJack F Vogel if (ret_val) { 314d035aa2dSJack F Vogel DEBUGOUT("Cannot determine PHY addr. Erroring out\n"); 3158cfa0ad2SJack F Vogel goto out; 3168cfa0ad2SJack F Vogel } 3178cfa0ad2SJack F Vogel } 3188cfa0ad2SJack F Vogel 3198cfa0ad2SJack F Vogel phy->id = 0; 3208cfa0ad2SJack F Vogel while ((e1000_phy_unknown == e1000_get_phy_type_from_id(phy->id)) && 3218cfa0ad2SJack F Vogel (i++ < 100)) { 3228cfa0ad2SJack F Vogel msec_delay(1); 3238cfa0ad2SJack F Vogel ret_val = e1000_get_phy_id(hw); 3248cfa0ad2SJack F Vogel if (ret_val) 3258cfa0ad2SJack F Vogel goto out; 3268cfa0ad2SJack F Vogel } 3278cfa0ad2SJack F Vogel 3288cfa0ad2SJack F Vogel /* Verify phy id */ 3298cfa0ad2SJack F Vogel switch (phy->id) { 3308cfa0ad2SJack F Vogel case IGP03E1000_E_PHY_ID: 3318cfa0ad2SJack F Vogel phy->type = e1000_phy_igp_3; 3328cfa0ad2SJack F Vogel phy->autoneg_mask = AUTONEG_ADVERTISE_SPEED_DEFAULT; 3334edd8523SJack F Vogel phy->ops.read_reg_locked = e1000_read_phy_reg_igp_locked; 3344edd8523SJack F Vogel phy->ops.write_reg_locked = e1000_write_phy_reg_igp_locked; 3354edd8523SJack F Vogel phy->ops.get_info = e1000_get_phy_info_igp; 3364edd8523SJack F Vogel phy->ops.check_polarity = e1000_check_polarity_igp; 3374edd8523SJack F Vogel phy->ops.force_speed_duplex = e1000_phy_force_speed_duplex_igp; 3388cfa0ad2SJack F Vogel break; 3398cfa0ad2SJack F Vogel case IFE_E_PHY_ID: 3408cfa0ad2SJack F Vogel case IFE_PLUS_E_PHY_ID: 3418cfa0ad2SJack F Vogel case IFE_C_E_PHY_ID: 3428cfa0ad2SJack F Vogel phy->type = e1000_phy_ife; 3438cfa0ad2SJack F Vogel phy->autoneg_mask = E1000_ALL_NOT_GIG; 3444edd8523SJack F Vogel phy->ops.get_info = e1000_get_phy_info_ife; 3454edd8523SJack F Vogel phy->ops.check_polarity = e1000_check_polarity_ife; 3464edd8523SJack F Vogel phy->ops.force_speed_duplex = e1000_phy_force_speed_duplex_ife; 3478cfa0ad2SJack F Vogel break; 3488cfa0ad2SJack F Vogel case BME1000_E_PHY_ID: 3498cfa0ad2SJack F Vogel phy->type = e1000_phy_bm; 3508cfa0ad2SJack F Vogel phy->autoneg_mask = AUTONEG_ADVERTISE_SPEED_DEFAULT; 3518cfa0ad2SJack F Vogel phy->ops.read_reg = e1000_read_phy_reg_bm; 3528cfa0ad2SJack F Vogel phy->ops.write_reg = e1000_write_phy_reg_bm; 3538cfa0ad2SJack F Vogel phy->ops.commit = e1000_phy_sw_reset_generic; 3544edd8523SJack F Vogel phy->ops.get_info = e1000_get_phy_info_m88; 3554edd8523SJack F Vogel phy->ops.check_polarity = e1000_check_polarity_m88; 3564edd8523SJack F Vogel phy->ops.force_speed_duplex = e1000_phy_force_speed_duplex_m88; 3578cfa0ad2SJack F Vogel break; 3588cfa0ad2SJack F Vogel default: 3598cfa0ad2SJack F Vogel ret_val = -E1000_ERR_PHY; 3608cfa0ad2SJack F Vogel goto out; 3618cfa0ad2SJack F Vogel } 3628cfa0ad2SJack F Vogel 3638cfa0ad2SJack F Vogel out: 3648cfa0ad2SJack F Vogel return ret_val; 3658cfa0ad2SJack F Vogel } 3668cfa0ad2SJack F Vogel 3678cfa0ad2SJack F Vogel /** 3688cfa0ad2SJack F Vogel * e1000_init_nvm_params_ich8lan - Initialize NVM function pointers 3698cfa0ad2SJack F Vogel * @hw: pointer to the HW structure 3708cfa0ad2SJack F Vogel * 3718cfa0ad2SJack F Vogel * Initialize family-specific NVM parameters and function 3728cfa0ad2SJack F Vogel * pointers. 3738cfa0ad2SJack F Vogel **/ 3748cfa0ad2SJack F Vogel static s32 e1000_init_nvm_params_ich8lan(struct e1000_hw *hw) 3758cfa0ad2SJack F Vogel { 3768cfa0ad2SJack F Vogel struct e1000_nvm_info *nvm = &hw->nvm; 377daf9197cSJack F Vogel struct e1000_dev_spec_ich8lan *dev_spec = &hw->dev_spec.ich8lan; 3788cfa0ad2SJack F Vogel u32 gfpreg, sector_base_addr, sector_end_addr; 3798cfa0ad2SJack F Vogel s32 ret_val = E1000_SUCCESS; 3808cfa0ad2SJack F Vogel u16 i; 3818cfa0ad2SJack F Vogel 3828cfa0ad2SJack F Vogel DEBUGFUNC("e1000_init_nvm_params_ich8lan"); 3838cfa0ad2SJack F Vogel 3848cfa0ad2SJack F Vogel /* Can't read flash registers if the register set isn't mapped. */ 3858cfa0ad2SJack F Vogel if (!hw->flash_address) { 3868cfa0ad2SJack F Vogel DEBUGOUT("ERROR: Flash registers not mapped\n"); 3878cfa0ad2SJack F Vogel ret_val = -E1000_ERR_CONFIG; 3888cfa0ad2SJack F Vogel goto out; 3898cfa0ad2SJack F Vogel } 3908cfa0ad2SJack F Vogel 3918cfa0ad2SJack F Vogel nvm->type = e1000_nvm_flash_sw; 3928cfa0ad2SJack F Vogel 3938cfa0ad2SJack F Vogel gfpreg = E1000_READ_FLASH_REG(hw, ICH_FLASH_GFPREG); 3948cfa0ad2SJack F Vogel 3958cfa0ad2SJack F Vogel /* 3968cfa0ad2SJack F Vogel * sector_X_addr is a "sector"-aligned address (4096 bytes) 3978cfa0ad2SJack F Vogel * Add 1 to sector_end_addr since this sector is included in 3988cfa0ad2SJack F Vogel * the overall size. 3998cfa0ad2SJack F Vogel */ 4008cfa0ad2SJack F Vogel sector_base_addr = gfpreg & FLASH_GFPREG_BASE_MASK; 4018cfa0ad2SJack F Vogel sector_end_addr = ((gfpreg >> 16) & FLASH_GFPREG_BASE_MASK) + 1; 4028cfa0ad2SJack F Vogel 4038cfa0ad2SJack F Vogel /* flash_base_addr is byte-aligned */ 4048cfa0ad2SJack F Vogel nvm->flash_base_addr = sector_base_addr << FLASH_SECTOR_ADDR_SHIFT; 4058cfa0ad2SJack F Vogel 4068cfa0ad2SJack F Vogel /* 4078cfa0ad2SJack F Vogel * find total size of the NVM, then cut in half since the total 4088cfa0ad2SJack F Vogel * size represents two separate NVM banks. 4098cfa0ad2SJack F Vogel */ 4108cfa0ad2SJack F Vogel nvm->flash_bank_size = (sector_end_addr - sector_base_addr) 4118cfa0ad2SJack F Vogel << FLASH_SECTOR_ADDR_SHIFT; 4128cfa0ad2SJack F Vogel nvm->flash_bank_size /= 2; 4138cfa0ad2SJack F Vogel /* Adjust to word count */ 4148cfa0ad2SJack F Vogel nvm->flash_bank_size /= sizeof(u16); 4158cfa0ad2SJack F Vogel 4168cfa0ad2SJack F Vogel nvm->word_size = E1000_SHADOW_RAM_WORDS; 4178cfa0ad2SJack F Vogel 4188cfa0ad2SJack F Vogel /* Clear shadow ram */ 4198cfa0ad2SJack F Vogel for (i = 0; i < nvm->word_size; i++) { 4208cfa0ad2SJack F Vogel dev_spec->shadow_ram[i].modified = FALSE; 4218cfa0ad2SJack F Vogel dev_spec->shadow_ram[i].value = 0xFFFF; 4228cfa0ad2SJack F Vogel } 4238cfa0ad2SJack F Vogel 4244edd8523SJack F Vogel E1000_MUTEX_INIT(&dev_spec->nvm_mutex); 4254edd8523SJack F Vogel E1000_MUTEX_INIT(&dev_spec->swflag_mutex); 4264edd8523SJack F Vogel 4278cfa0ad2SJack F Vogel /* Function Pointers */ 4284edd8523SJack F Vogel nvm->ops.acquire = e1000_acquire_nvm_ich8lan; 4294edd8523SJack F Vogel nvm->ops.release = e1000_release_nvm_ich8lan; 4308cfa0ad2SJack F Vogel nvm->ops.read = e1000_read_nvm_ich8lan; 4318cfa0ad2SJack F Vogel nvm->ops.update = e1000_update_nvm_checksum_ich8lan; 4328cfa0ad2SJack F Vogel nvm->ops.valid_led_default = e1000_valid_led_default_ich8lan; 4338cfa0ad2SJack F Vogel nvm->ops.validate = e1000_validate_nvm_checksum_ich8lan; 4348cfa0ad2SJack F Vogel nvm->ops.write = e1000_write_nvm_ich8lan; 4358cfa0ad2SJack F Vogel 4368cfa0ad2SJack F Vogel out: 4378cfa0ad2SJack F Vogel return ret_val; 4388cfa0ad2SJack F Vogel } 4398cfa0ad2SJack F Vogel 4408cfa0ad2SJack F Vogel /** 4418cfa0ad2SJack F Vogel * e1000_init_mac_params_ich8lan - Initialize MAC function pointers 4428cfa0ad2SJack F Vogel * @hw: pointer to the HW structure 4438cfa0ad2SJack F Vogel * 4448cfa0ad2SJack F Vogel * Initialize family-specific MAC parameters and function 4458cfa0ad2SJack F Vogel * pointers. 4468cfa0ad2SJack F Vogel **/ 4478cfa0ad2SJack F Vogel static s32 e1000_init_mac_params_ich8lan(struct e1000_hw *hw) 4488cfa0ad2SJack F Vogel { 4498cfa0ad2SJack F Vogel struct e1000_mac_info *mac = &hw->mac; 450d035aa2dSJack F Vogel u16 pci_cfg; 4518cfa0ad2SJack F Vogel 4528cfa0ad2SJack F Vogel DEBUGFUNC("e1000_init_mac_params_ich8lan"); 4538cfa0ad2SJack F Vogel 4548cfa0ad2SJack F Vogel /* Set media type function pointer */ 4558cfa0ad2SJack F Vogel hw->phy.media_type = e1000_media_type_copper; 4568cfa0ad2SJack F Vogel 4578cfa0ad2SJack F Vogel /* Set mta register count */ 4588cfa0ad2SJack F Vogel mac->mta_reg_count = 32; 4598cfa0ad2SJack F Vogel /* Set rar entry count */ 4608cfa0ad2SJack F Vogel mac->rar_entry_count = E1000_ICH_RAR_ENTRIES; 4618cfa0ad2SJack F Vogel if (mac->type == e1000_ich8lan) 4628cfa0ad2SJack F Vogel mac->rar_entry_count--; 4638cfa0ad2SJack F Vogel /* Set if part includes ASF firmware */ 4648cfa0ad2SJack F Vogel mac->asf_firmware_present = TRUE; 4658ec87fc5SJack F Vogel /* FWSM register */ 4668ec87fc5SJack F Vogel mac->has_fwsm = TRUE; 4678ec87fc5SJack F Vogel /* ARC subsystem not supported */ 4688ec87fc5SJack F Vogel mac->arc_subsystem_valid = FALSE; 4694edd8523SJack F Vogel /* Adaptive IFS supported */ 4704edd8523SJack F Vogel mac->adaptive_ifs = TRUE; 4718cfa0ad2SJack F Vogel 4728cfa0ad2SJack F Vogel /* Function pointers */ 4738cfa0ad2SJack F Vogel 4748cfa0ad2SJack F Vogel /* bus type/speed/width */ 4758cfa0ad2SJack F Vogel mac->ops.get_bus_info = e1000_get_bus_info_ich8lan; 476daf9197cSJack F Vogel /* function id */ 477daf9197cSJack F Vogel mac->ops.set_lan_id = e1000_set_lan_id_single_port; 4788cfa0ad2SJack F Vogel /* reset */ 4798cfa0ad2SJack F Vogel mac->ops.reset_hw = e1000_reset_hw_ich8lan; 4808cfa0ad2SJack F Vogel /* hw initialization */ 4818cfa0ad2SJack F Vogel mac->ops.init_hw = e1000_init_hw_ich8lan; 4828cfa0ad2SJack F Vogel /* link setup */ 4838cfa0ad2SJack F Vogel mac->ops.setup_link = e1000_setup_link_ich8lan; 4848cfa0ad2SJack F Vogel /* physical interface setup */ 4858cfa0ad2SJack F Vogel mac->ops.setup_physical_interface = e1000_setup_copper_link_ich8lan; 4868cfa0ad2SJack F Vogel /* check for link */ 4874edd8523SJack F Vogel mac->ops.check_for_link = e1000_check_for_copper_link_ich8lan; 4888cfa0ad2SJack F Vogel /* check management mode */ 4898cfa0ad2SJack F Vogel mac->ops.check_mng_mode = e1000_check_mng_mode_ich8lan; 4908cfa0ad2SJack F Vogel /* link info */ 4918cfa0ad2SJack F Vogel mac->ops.get_link_up_info = e1000_get_link_up_info_ich8lan; 4928cfa0ad2SJack F Vogel /* multicast address update */ 4938cfa0ad2SJack F Vogel mac->ops.update_mc_addr_list = e1000_update_mc_addr_list_generic; 494d035aa2dSJack F Vogel /* clear hardware counters */ 495d035aa2dSJack F Vogel mac->ops.clear_hw_cntrs = e1000_clear_hw_cntrs_ich8lan; 496d035aa2dSJack F Vogel 497d035aa2dSJack F Vogel /* LED operations */ 498d035aa2dSJack F Vogel switch (mac->type) { 499d035aa2dSJack F Vogel case e1000_ich8lan: 500d035aa2dSJack F Vogel case e1000_ich9lan: 501d035aa2dSJack F Vogel case e1000_ich10lan: 502d035aa2dSJack F Vogel /* ID LED init */ 503d035aa2dSJack F Vogel mac->ops.id_led_init = e1000_id_led_init_generic; 5048cfa0ad2SJack F Vogel /* blink LED */ 5058cfa0ad2SJack F Vogel mac->ops.blink_led = e1000_blink_led_generic; 5068cfa0ad2SJack F Vogel /* setup LED */ 5078cfa0ad2SJack F Vogel mac->ops.setup_led = e1000_setup_led_generic; 5088cfa0ad2SJack F Vogel /* cleanup LED */ 5098cfa0ad2SJack F Vogel mac->ops.cleanup_led = e1000_cleanup_led_ich8lan; 5108cfa0ad2SJack F Vogel /* turn on/off LED */ 5118cfa0ad2SJack F Vogel mac->ops.led_on = e1000_led_on_ich8lan; 5128cfa0ad2SJack F Vogel mac->ops.led_off = e1000_led_off_ich8lan; 513d035aa2dSJack F Vogel break; 5149d81738fSJack F Vogel case e1000_pchlan: 5159d81738fSJack F Vogel /* save PCH revision_id */ 5169d81738fSJack F Vogel e1000_read_pci_cfg(hw, 0x2, &pci_cfg); 5179d81738fSJack F Vogel hw->revision_id = (u8)(pci_cfg &= 0x000F); 5189d81738fSJack F Vogel /* ID LED init */ 5199d81738fSJack F Vogel mac->ops.id_led_init = e1000_id_led_init_pchlan; 5209d81738fSJack F Vogel /* setup LED */ 5219d81738fSJack F Vogel mac->ops.setup_led = e1000_setup_led_pchlan; 5229d81738fSJack F Vogel /* cleanup LED */ 5239d81738fSJack F Vogel mac->ops.cleanup_led = e1000_cleanup_led_pchlan; 5249d81738fSJack F Vogel /* turn on/off LED */ 5259d81738fSJack F Vogel mac->ops.led_on = e1000_led_on_pchlan; 5269d81738fSJack F Vogel mac->ops.led_off = e1000_led_off_pchlan; 5279d81738fSJack F Vogel break; 528d035aa2dSJack F Vogel default: 529d035aa2dSJack F Vogel break; 530d035aa2dSJack F Vogel } 5318cfa0ad2SJack F Vogel 5328cfa0ad2SJack F Vogel /* Enable PCS Lock-loss workaround for ICH8 */ 5338cfa0ad2SJack F Vogel if (mac->type == e1000_ich8lan) 5348cfa0ad2SJack F Vogel e1000_set_kmrn_lock_loss_workaround_ich8lan(hw, TRUE); 5358cfa0ad2SJack F Vogel 536daf9197cSJack F Vogel return E1000_SUCCESS; 5378cfa0ad2SJack F Vogel } 5388cfa0ad2SJack F Vogel 5398cfa0ad2SJack F Vogel /** 5404edd8523SJack F Vogel * e1000_check_for_copper_link_ich8lan - Check for link (Copper) 5414edd8523SJack F Vogel * @hw: pointer to the HW structure 5424edd8523SJack F Vogel * 5434edd8523SJack F Vogel * Checks to see of the link status of the hardware has changed. If a 5444edd8523SJack F Vogel * change in link status has been detected, then we read the PHY registers 5454edd8523SJack F Vogel * to get the current speed/duplex if link exists. 5464edd8523SJack F Vogel **/ 5474edd8523SJack F Vogel static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw) 5484edd8523SJack F Vogel { 5494edd8523SJack F Vogel struct e1000_mac_info *mac = &hw->mac; 5504edd8523SJack F Vogel s32 ret_val; 5514edd8523SJack F Vogel bool link; 5524edd8523SJack F Vogel 5534edd8523SJack F Vogel DEBUGFUNC("e1000_check_for_copper_link_ich8lan"); 5544edd8523SJack F Vogel 5554edd8523SJack F Vogel /* 5564edd8523SJack F Vogel * We only want to go out to the PHY registers to see if Auto-Neg 5574edd8523SJack F Vogel * has completed and/or if our link status has changed. The 5584edd8523SJack F Vogel * get_link_status flag is set upon receiving a Link Status 5594edd8523SJack F Vogel * Change or Rx Sequence Error interrupt. 5604edd8523SJack F Vogel */ 5614edd8523SJack F Vogel if (!mac->get_link_status) { 5624edd8523SJack F Vogel ret_val = E1000_SUCCESS; 5634edd8523SJack F Vogel goto out; 5644edd8523SJack F Vogel } 5654edd8523SJack F Vogel 5664edd8523SJack F Vogel /* 5674edd8523SJack F Vogel * First we want to see if the MII Status Register reports 5684edd8523SJack F Vogel * link. If so, then we want to get the current speed/duplex 5694edd8523SJack F Vogel * of the PHY. 5704edd8523SJack F Vogel */ 5714edd8523SJack F Vogel ret_val = e1000_phy_has_link_generic(hw, 1, 0, &link); 5724edd8523SJack F Vogel if (ret_val) 5734edd8523SJack F Vogel goto out; 5744edd8523SJack F Vogel 5754edd8523SJack F Vogel if (hw->mac.type == e1000_pchlan) { 5764edd8523SJack F Vogel ret_val = e1000_k1_gig_workaround_hv(hw, link); 5774edd8523SJack F Vogel if (ret_val) 5784edd8523SJack F Vogel goto out; 5794edd8523SJack F Vogel } 5804edd8523SJack F Vogel 5814edd8523SJack F Vogel if (!link) 5824edd8523SJack F Vogel goto out; /* No link detected */ 5834edd8523SJack F Vogel 5844edd8523SJack F Vogel mac->get_link_status = FALSE; 5854edd8523SJack F Vogel 5864edd8523SJack F Vogel if (hw->phy.type == e1000_phy_82578) { 5874edd8523SJack F Vogel ret_val = e1000_link_stall_workaround_hv(hw); 5884edd8523SJack F Vogel if (ret_val) 5894edd8523SJack F Vogel goto out; 5904edd8523SJack F Vogel } 5914edd8523SJack F Vogel 5924edd8523SJack F Vogel /* 5934edd8523SJack F Vogel * Check if there was DownShift, must be checked 5944edd8523SJack F Vogel * immediately after link-up 5954edd8523SJack F Vogel */ 5964edd8523SJack F Vogel e1000_check_downshift_generic(hw); 5974edd8523SJack F Vogel 5984edd8523SJack F Vogel /* 5994edd8523SJack F Vogel * If we are forcing speed/duplex, then we simply return since 6004edd8523SJack F Vogel * we have already determined whether we have link or not. 6014edd8523SJack F Vogel */ 6024edd8523SJack F Vogel if (!mac->autoneg) { 6034edd8523SJack F Vogel ret_val = -E1000_ERR_CONFIG; 6044edd8523SJack F Vogel goto out; 6054edd8523SJack F Vogel } 6064edd8523SJack F Vogel 6074edd8523SJack F Vogel /* 6084edd8523SJack F Vogel * Auto-Neg is enabled. Auto Speed Detection takes care 6094edd8523SJack F Vogel * of MAC speed/duplex configuration. So we only need to 6104edd8523SJack F Vogel * configure Collision Distance in the MAC. 6114edd8523SJack F Vogel */ 6124edd8523SJack F Vogel e1000_config_collision_dist_generic(hw); 6134edd8523SJack F Vogel 6144edd8523SJack F Vogel /* 6154edd8523SJack F Vogel * Configure Flow Control now that Auto-Neg has completed. 6164edd8523SJack F Vogel * First, we need to restore the desired flow control 6174edd8523SJack F Vogel * settings because we may have had to re-autoneg with a 6184edd8523SJack F Vogel * different link partner. 6194edd8523SJack F Vogel */ 6204edd8523SJack F Vogel ret_val = e1000_config_fc_after_link_up_generic(hw); 6214edd8523SJack F Vogel if (ret_val) 6224edd8523SJack F Vogel DEBUGOUT("Error configuring flow control\n"); 6234edd8523SJack F Vogel 6244edd8523SJack F Vogel out: 6254edd8523SJack F Vogel return ret_val; 6264edd8523SJack F Vogel } 6274edd8523SJack F Vogel 6284edd8523SJack F Vogel /** 6298cfa0ad2SJack F Vogel * e1000_init_function_pointers_ich8lan - Initialize ICH8 function pointers 6308cfa0ad2SJack F Vogel * @hw: pointer to the HW structure 6318cfa0ad2SJack F Vogel * 6328cfa0ad2SJack F Vogel * Initialize family-specific function pointers for PHY, MAC, and NVM. 6338cfa0ad2SJack F Vogel **/ 6348cfa0ad2SJack F Vogel void e1000_init_function_pointers_ich8lan(struct e1000_hw *hw) 6358cfa0ad2SJack F Vogel { 6368cfa0ad2SJack F Vogel DEBUGFUNC("e1000_init_function_pointers_ich8lan"); 6378cfa0ad2SJack F Vogel 6388cfa0ad2SJack F Vogel hw->mac.ops.init_params = e1000_init_mac_params_ich8lan; 6398cfa0ad2SJack F Vogel hw->nvm.ops.init_params = e1000_init_nvm_params_ich8lan; 6409d81738fSJack F Vogel switch (hw->mac.type) { 6419d81738fSJack F Vogel case e1000_ich8lan: 6429d81738fSJack F Vogel case e1000_ich9lan: 6439d81738fSJack F Vogel case e1000_ich10lan: 6448cfa0ad2SJack F Vogel hw->phy.ops.init_params = e1000_init_phy_params_ich8lan; 6459d81738fSJack F Vogel break; 6469d81738fSJack F Vogel case e1000_pchlan: 6479d81738fSJack F Vogel hw->phy.ops.init_params = e1000_init_phy_params_pchlan; 6489d81738fSJack F Vogel break; 6499d81738fSJack F Vogel default: 6509d81738fSJack F Vogel break; 6519d81738fSJack F Vogel } 6528cfa0ad2SJack F Vogel } 6538cfa0ad2SJack F Vogel 6548cfa0ad2SJack F Vogel /** 6554edd8523SJack F Vogel * e1000_acquire_nvm_ich8lan - Acquire NVM mutex 6564edd8523SJack F Vogel * @hw: pointer to the HW structure 6574edd8523SJack F Vogel * 6584edd8523SJack F Vogel * Acquires the mutex for performing NVM operations. 6594edd8523SJack F Vogel **/ 6604edd8523SJack F Vogel static s32 e1000_acquire_nvm_ich8lan(struct e1000_hw *hw) 6614edd8523SJack F Vogel { 6624edd8523SJack F Vogel DEBUGFUNC("e1000_acquire_nvm_ich8lan"); 6634edd8523SJack F Vogel 6644edd8523SJack F Vogel E1000_MUTEX_LOCK(&hw->dev_spec.ich8lan.nvm_mutex); 6654edd8523SJack F Vogel 6664edd8523SJack F Vogel return E1000_SUCCESS; 6674edd8523SJack F Vogel } 6684edd8523SJack F Vogel 6694edd8523SJack F Vogel /** 6704edd8523SJack F Vogel * e1000_release_nvm_ich8lan - Release NVM mutex 6714edd8523SJack F Vogel * @hw: pointer to the HW structure 6724edd8523SJack F Vogel * 6734edd8523SJack F Vogel * Releases the mutex used while performing NVM operations. 6744edd8523SJack F Vogel **/ 6754edd8523SJack F Vogel static void e1000_release_nvm_ich8lan(struct e1000_hw *hw) 6764edd8523SJack F Vogel { 6774edd8523SJack F Vogel DEBUGFUNC("e1000_release_nvm_ich8lan"); 6784edd8523SJack F Vogel 6794edd8523SJack F Vogel E1000_MUTEX_UNLOCK(&hw->dev_spec.ich8lan.nvm_mutex); 6804edd8523SJack F Vogel 6814edd8523SJack F Vogel return; 6824edd8523SJack F Vogel } 6834edd8523SJack F Vogel 6844edd8523SJack F Vogel /** 6858cfa0ad2SJack F Vogel * e1000_acquire_swflag_ich8lan - Acquire software control flag 6868cfa0ad2SJack F Vogel * @hw: pointer to the HW structure 6878cfa0ad2SJack F Vogel * 6884edd8523SJack F Vogel * Acquires the software control flag for performing PHY and select 6894edd8523SJack F Vogel * MAC CSR accesses. 6908cfa0ad2SJack F Vogel **/ 6918cfa0ad2SJack F Vogel static s32 e1000_acquire_swflag_ich8lan(struct e1000_hw *hw) 6928cfa0ad2SJack F Vogel { 6938cfa0ad2SJack F Vogel u32 extcnf_ctrl, timeout = PHY_CFG_TIMEOUT; 6948cfa0ad2SJack F Vogel s32 ret_val = E1000_SUCCESS; 6958cfa0ad2SJack F Vogel 6968cfa0ad2SJack F Vogel DEBUGFUNC("e1000_acquire_swflag_ich8lan"); 6978cfa0ad2SJack F Vogel 6984edd8523SJack F Vogel E1000_MUTEX_LOCK(&hw->dev_spec.ich8lan.swflag_mutex); 6994edd8523SJack F Vogel 7008cfa0ad2SJack F Vogel while (timeout) { 7018cfa0ad2SJack F Vogel extcnf_ctrl = E1000_READ_REG(hw, E1000_EXTCNF_CTRL); 7024edd8523SJack F Vogel if (!(extcnf_ctrl & E1000_EXTCNF_CTRL_SWFLAG)) 7038cfa0ad2SJack F Vogel break; 7044edd8523SJack F Vogel 7058cfa0ad2SJack F Vogel msec_delay_irq(1); 7068cfa0ad2SJack F Vogel timeout--; 7078cfa0ad2SJack F Vogel } 7088cfa0ad2SJack F Vogel 7098cfa0ad2SJack F Vogel if (!timeout) { 7109d81738fSJack F Vogel DEBUGOUT("SW/FW/HW has locked the resource for too long.\n"); 7114edd8523SJack F Vogel ret_val = -E1000_ERR_CONFIG; 7124edd8523SJack F Vogel goto out; 7134edd8523SJack F Vogel } 7144edd8523SJack F Vogel 7154edd8523SJack F Vogel timeout = SW_FLAG_TIMEOUT; 7164edd8523SJack F Vogel 7174edd8523SJack F Vogel extcnf_ctrl |= E1000_EXTCNF_CTRL_SWFLAG; 7184edd8523SJack F Vogel E1000_WRITE_REG(hw, E1000_EXTCNF_CTRL, extcnf_ctrl); 7194edd8523SJack F Vogel 7204edd8523SJack F Vogel while (timeout) { 7214edd8523SJack F Vogel extcnf_ctrl = E1000_READ_REG(hw, E1000_EXTCNF_CTRL); 7224edd8523SJack F Vogel if (extcnf_ctrl & E1000_EXTCNF_CTRL_SWFLAG) 7234edd8523SJack F Vogel break; 7244edd8523SJack F Vogel 7254edd8523SJack F Vogel msec_delay_irq(1); 7264edd8523SJack F Vogel timeout--; 7274edd8523SJack F Vogel } 7284edd8523SJack F Vogel 7294edd8523SJack F Vogel if (!timeout) { 7304edd8523SJack F Vogel DEBUGOUT("Failed to acquire the semaphore.\n"); 7318cfa0ad2SJack F Vogel extcnf_ctrl &= ~E1000_EXTCNF_CTRL_SWFLAG; 7328cfa0ad2SJack F Vogel E1000_WRITE_REG(hw, E1000_EXTCNF_CTRL, extcnf_ctrl); 7338cfa0ad2SJack F Vogel ret_val = -E1000_ERR_CONFIG; 7348cfa0ad2SJack F Vogel goto out; 7358cfa0ad2SJack F Vogel } 7368cfa0ad2SJack F Vogel 7378cfa0ad2SJack F Vogel out: 7384edd8523SJack F Vogel if (ret_val) 7394edd8523SJack F Vogel E1000_MUTEX_UNLOCK(&hw->dev_spec.ich8lan.swflag_mutex); 7404edd8523SJack F Vogel 7418cfa0ad2SJack F Vogel return ret_val; 7428cfa0ad2SJack F Vogel } 7438cfa0ad2SJack F Vogel 7448cfa0ad2SJack F Vogel /** 7458cfa0ad2SJack F Vogel * e1000_release_swflag_ich8lan - Release software control flag 7468cfa0ad2SJack F Vogel * @hw: pointer to the HW structure 7478cfa0ad2SJack F Vogel * 7484edd8523SJack F Vogel * Releases the software control flag for performing PHY and select 7494edd8523SJack F Vogel * MAC CSR accesses. 7508cfa0ad2SJack F Vogel **/ 7518cfa0ad2SJack F Vogel static void e1000_release_swflag_ich8lan(struct e1000_hw *hw) 7528cfa0ad2SJack F Vogel { 7538cfa0ad2SJack F Vogel u32 extcnf_ctrl; 7548cfa0ad2SJack F Vogel 7558cfa0ad2SJack F Vogel DEBUGFUNC("e1000_release_swflag_ich8lan"); 7568cfa0ad2SJack F Vogel 7578cfa0ad2SJack F Vogel extcnf_ctrl = E1000_READ_REG(hw, E1000_EXTCNF_CTRL); 7588cfa0ad2SJack F Vogel extcnf_ctrl &= ~E1000_EXTCNF_CTRL_SWFLAG; 7598cfa0ad2SJack F Vogel E1000_WRITE_REG(hw, E1000_EXTCNF_CTRL, extcnf_ctrl); 7608cfa0ad2SJack F Vogel 7614edd8523SJack F Vogel E1000_MUTEX_UNLOCK(&hw->dev_spec.ich8lan.swflag_mutex); 7624edd8523SJack F Vogel 7638cfa0ad2SJack F Vogel return; 7648cfa0ad2SJack F Vogel } 7658cfa0ad2SJack F Vogel 7668cfa0ad2SJack F Vogel /** 7678cfa0ad2SJack F Vogel * e1000_check_mng_mode_ich8lan - Checks management mode 7688cfa0ad2SJack F Vogel * @hw: pointer to the HW structure 7698cfa0ad2SJack F Vogel * 7708cfa0ad2SJack F Vogel * This checks if the adapter has manageability enabled. 7718cfa0ad2SJack F Vogel * This is a function pointer entry point only called by read/write 7728cfa0ad2SJack F Vogel * routines for the PHY and NVM parts. 7738cfa0ad2SJack F Vogel **/ 7748cfa0ad2SJack F Vogel static bool e1000_check_mng_mode_ich8lan(struct e1000_hw *hw) 7758cfa0ad2SJack F Vogel { 7768cfa0ad2SJack F Vogel u32 fwsm; 7778cfa0ad2SJack F Vogel 7788cfa0ad2SJack F Vogel DEBUGFUNC("e1000_check_mng_mode_ich8lan"); 7798cfa0ad2SJack F Vogel 7808cfa0ad2SJack F Vogel fwsm = E1000_READ_REG(hw, E1000_FWSM); 7818cfa0ad2SJack F Vogel 782daf9197cSJack F Vogel return (fwsm & E1000_FWSM_MODE_MASK) == 783daf9197cSJack F Vogel (E1000_ICH_MNG_IAMT_MODE << E1000_FWSM_MODE_SHIFT); 7848cfa0ad2SJack F Vogel } 7858cfa0ad2SJack F Vogel 7868cfa0ad2SJack F Vogel /** 7878cfa0ad2SJack F Vogel * e1000_check_reset_block_ich8lan - Check if PHY reset is blocked 7888cfa0ad2SJack F Vogel * @hw: pointer to the HW structure 7898cfa0ad2SJack F Vogel * 7908cfa0ad2SJack F Vogel * Checks if firmware is blocking the reset of the PHY. 7918cfa0ad2SJack F Vogel * This is a function pointer entry point only called by 7928cfa0ad2SJack F Vogel * reset routines. 7938cfa0ad2SJack F Vogel **/ 7948cfa0ad2SJack F Vogel static s32 e1000_check_reset_block_ich8lan(struct e1000_hw *hw) 7958cfa0ad2SJack F Vogel { 7968cfa0ad2SJack F Vogel u32 fwsm; 7978cfa0ad2SJack F Vogel 7988cfa0ad2SJack F Vogel DEBUGFUNC("e1000_check_reset_block_ich8lan"); 7998cfa0ad2SJack F Vogel 8008ec87fc5SJack F Vogel if (hw->phy.reset_disable) 8018ec87fc5SJack F Vogel return E1000_BLK_PHY_RESET; 8028ec87fc5SJack F Vogel 8038cfa0ad2SJack F Vogel fwsm = E1000_READ_REG(hw, E1000_FWSM); 8048cfa0ad2SJack F Vogel 8058cfa0ad2SJack F Vogel return (fwsm & E1000_ICH_FWSM_RSPCIPHY) ? E1000_SUCCESS 8068cfa0ad2SJack F Vogel : E1000_BLK_PHY_RESET; 8078cfa0ad2SJack F Vogel } 8088cfa0ad2SJack F Vogel 8098cfa0ad2SJack F Vogel /** 8104edd8523SJack F Vogel * e1000_sw_lcd_config_ich8lan - SW-based LCD Configuration 8114edd8523SJack F Vogel * @hw: pointer to the HW structure 8124edd8523SJack F Vogel * 8134edd8523SJack F Vogel * SW should configure the LCD from the NVM extended configuration region 8144edd8523SJack F Vogel * as a workaround for certain parts. 8154edd8523SJack F Vogel **/ 8164edd8523SJack F Vogel static s32 e1000_sw_lcd_config_ich8lan(struct e1000_hw *hw) 8174edd8523SJack F Vogel { 8184edd8523SJack F Vogel struct e1000_phy_info *phy = &hw->phy; 8194edd8523SJack F Vogel u32 i, data, cnf_size, cnf_base_addr, sw_cfg_mask; 820a69ed8dfSJack F Vogel s32 ret_val = E1000_SUCCESS; 8214edd8523SJack F Vogel u16 word_addr, reg_data, reg_addr, phy_page = 0; 8224edd8523SJack F Vogel 823a69ed8dfSJack F Vogel if (!(hw->mac.type == e1000_ich8lan && phy->type == e1000_phy_igp_3) && 824a69ed8dfSJack F Vogel !(hw->mac.type == e1000_pchlan)) 825a69ed8dfSJack F Vogel return ret_val; 826a69ed8dfSJack F Vogel 8274edd8523SJack F Vogel ret_val = hw->phy.ops.acquire(hw); 8284edd8523SJack F Vogel if (ret_val) 8294edd8523SJack F Vogel return ret_val; 8304edd8523SJack F Vogel 8314edd8523SJack F Vogel /* 8324edd8523SJack F Vogel * Initialize the PHY from the NVM on ICH platforms. This 8334edd8523SJack F Vogel * is needed due to an issue where the NVM configuration is 8344edd8523SJack F Vogel * not properly autoloaded after power transitions. 8354edd8523SJack F Vogel * Therefore, after each PHY reset, we will load the 8364edd8523SJack F Vogel * configuration data out of the NVM manually. 8374edd8523SJack F Vogel */ 8384edd8523SJack F Vogel if ((hw->device_id == E1000_DEV_ID_ICH8_IGP_M_AMT) || 8394edd8523SJack F Vogel (hw->device_id == E1000_DEV_ID_ICH8_IGP_M) || 8404edd8523SJack F Vogel (hw->mac.type == e1000_pchlan)) 8414edd8523SJack F Vogel sw_cfg_mask = E1000_FEXTNVM_SW_CONFIG_ICH8M; 8424edd8523SJack F Vogel else 8434edd8523SJack F Vogel sw_cfg_mask = E1000_FEXTNVM_SW_CONFIG; 8444edd8523SJack F Vogel 8454edd8523SJack F Vogel data = E1000_READ_REG(hw, E1000_FEXTNVM); 8464edd8523SJack F Vogel if (!(data & sw_cfg_mask)) 8474edd8523SJack F Vogel goto out; 8484edd8523SJack F Vogel 8494edd8523SJack F Vogel /* Wait for basic configuration completes before proceeding */ 8504edd8523SJack F Vogel e1000_lan_init_done_ich8lan(hw); 8514edd8523SJack F Vogel 8524edd8523SJack F Vogel /* 8534edd8523SJack F Vogel * Make sure HW does not configure LCD from PHY 8544edd8523SJack F Vogel * extended configuration before SW configuration 8554edd8523SJack F Vogel */ 8564edd8523SJack F Vogel data = E1000_READ_REG(hw, E1000_EXTCNF_CTRL); 8574edd8523SJack F Vogel if (data & E1000_EXTCNF_CTRL_LCD_WRITE_ENABLE) 8584edd8523SJack F Vogel goto out; 8594edd8523SJack F Vogel 8604edd8523SJack F Vogel cnf_size = E1000_READ_REG(hw, E1000_EXTCNF_SIZE); 8614edd8523SJack F Vogel cnf_size &= E1000_EXTCNF_SIZE_EXT_PCIE_LENGTH_MASK; 8624edd8523SJack F Vogel cnf_size >>= E1000_EXTCNF_SIZE_EXT_PCIE_LENGTH_SHIFT; 8634edd8523SJack F Vogel if (!cnf_size) 8644edd8523SJack F Vogel goto out; 8654edd8523SJack F Vogel 8664edd8523SJack F Vogel cnf_base_addr = data & E1000_EXTCNF_CTRL_EXT_CNF_POINTER_MASK; 8674edd8523SJack F Vogel cnf_base_addr >>= E1000_EXTCNF_CTRL_EXT_CNF_POINTER_SHIFT; 8684edd8523SJack F Vogel 8694edd8523SJack F Vogel if (!(data & E1000_EXTCNF_CTRL_OEM_WRITE_ENABLE) && 8704edd8523SJack F Vogel (hw->mac.type == e1000_pchlan)) { 8714edd8523SJack F Vogel /* 8724edd8523SJack F Vogel * HW configures the SMBus address and LEDs when the 8734edd8523SJack F Vogel * OEM and LCD Write Enable bits are set in the NVM. 8744edd8523SJack F Vogel * When both NVM bits are cleared, SW will configure 8754edd8523SJack F Vogel * them instead. 8764edd8523SJack F Vogel */ 8774edd8523SJack F Vogel data = E1000_READ_REG(hw, E1000_STRAP); 8784edd8523SJack F Vogel data &= E1000_STRAP_SMBUS_ADDRESS_MASK; 8794edd8523SJack F Vogel reg_data = data >> E1000_STRAP_SMBUS_ADDRESS_SHIFT; 8804edd8523SJack F Vogel reg_data |= HV_SMB_ADDR_PEC_EN | HV_SMB_ADDR_VALID; 8814edd8523SJack F Vogel ret_val = e1000_write_phy_reg_hv_locked(hw, HV_SMB_ADDR, 8824edd8523SJack F Vogel reg_data); 8834edd8523SJack F Vogel if (ret_val) 8844edd8523SJack F Vogel goto out; 8854edd8523SJack F Vogel 8864edd8523SJack F Vogel data = E1000_READ_REG(hw, E1000_LEDCTL); 887a69ed8dfSJack F Vogel ret_val = e1000_write_phy_reg_hv_locked(hw, HV_LED_CONFIG, 8884edd8523SJack F Vogel (u16)data); 8894edd8523SJack F Vogel if (ret_val) 8904edd8523SJack F Vogel goto out; 8914edd8523SJack F Vogel } 8924edd8523SJack F Vogel 8934edd8523SJack F Vogel /* Configure LCD from extended configuration region. */ 8944edd8523SJack F Vogel 8954edd8523SJack F Vogel /* cnf_base_addr is in DWORD */ 8964edd8523SJack F Vogel word_addr = (u16)(cnf_base_addr << 1); 8974edd8523SJack F Vogel 8984edd8523SJack F Vogel for (i = 0; i < cnf_size; i++) { 8994edd8523SJack F Vogel ret_val = hw->nvm.ops.read(hw, (word_addr + i * 2), 1, 9004edd8523SJack F Vogel ®_data); 9014edd8523SJack F Vogel if (ret_val) 9024edd8523SJack F Vogel goto out; 9034edd8523SJack F Vogel 9044edd8523SJack F Vogel ret_val = hw->nvm.ops.read(hw, (word_addr + i * 2 + 1), 9054edd8523SJack F Vogel 1, ®_addr); 9064edd8523SJack F Vogel if (ret_val) 9074edd8523SJack F Vogel goto out; 9084edd8523SJack F Vogel 9094edd8523SJack F Vogel /* Save off the PHY page for future writes. */ 9104edd8523SJack F Vogel if (reg_addr == IGP01E1000_PHY_PAGE_SELECT) { 9114edd8523SJack F Vogel phy_page = reg_data; 9124edd8523SJack F Vogel continue; 9134edd8523SJack F Vogel } 9144edd8523SJack F Vogel 9154edd8523SJack F Vogel reg_addr &= PHY_REG_MASK; 9164edd8523SJack F Vogel reg_addr |= phy_page; 9174edd8523SJack F Vogel 9184edd8523SJack F Vogel ret_val = phy->ops.write_reg_locked(hw, (u32)reg_addr, 9194edd8523SJack F Vogel reg_data); 9204edd8523SJack F Vogel if (ret_val) 9214edd8523SJack F Vogel goto out; 9224edd8523SJack F Vogel } 9234edd8523SJack F Vogel 9244edd8523SJack F Vogel out: 9254edd8523SJack F Vogel hw->phy.ops.release(hw); 9264edd8523SJack F Vogel return ret_val; 9274edd8523SJack F Vogel } 9284edd8523SJack F Vogel 9294edd8523SJack F Vogel /** 9304edd8523SJack F Vogel * e1000_k1_gig_workaround_hv - K1 Si workaround 9314edd8523SJack F Vogel * @hw: pointer to the HW structure 9324edd8523SJack F Vogel * @link: link up bool flag 9334edd8523SJack F Vogel * 9344edd8523SJack F Vogel * If K1 is enabled for 1Gbps, the MAC might stall when transitioning 9354edd8523SJack F Vogel * from a lower speed. This workaround disables K1 whenever link is at 1Gig 9364edd8523SJack F Vogel * If link is down, the function will restore the default K1 setting located 9374edd8523SJack F Vogel * in the NVM. 9384edd8523SJack F Vogel **/ 9394edd8523SJack F Vogel static s32 e1000_k1_gig_workaround_hv(struct e1000_hw *hw, bool link) 9404edd8523SJack F Vogel { 9414edd8523SJack F Vogel s32 ret_val = E1000_SUCCESS; 9424edd8523SJack F Vogel u16 status_reg = 0; 9434edd8523SJack F Vogel bool k1_enable = hw->dev_spec.ich8lan.nvm_k1_enabled; 9444edd8523SJack F Vogel 9454edd8523SJack F Vogel DEBUGFUNC("e1000_k1_gig_workaround_hv"); 9464edd8523SJack F Vogel 9474edd8523SJack F Vogel if (hw->mac.type != e1000_pchlan) 9484edd8523SJack F Vogel goto out; 9494edd8523SJack F Vogel 9504edd8523SJack F Vogel /* Wrap the whole flow with the sw flag */ 9514edd8523SJack F Vogel ret_val = hw->phy.ops.acquire(hw); 9524edd8523SJack F Vogel if (ret_val) 9534edd8523SJack F Vogel goto out; 9544edd8523SJack F Vogel 9554edd8523SJack F Vogel /* Disable K1 when link is 1Gbps, otherwise use the NVM setting */ 9564edd8523SJack F Vogel if (link) { 9574edd8523SJack F Vogel if (hw->phy.type == e1000_phy_82578) { 9584edd8523SJack F Vogel ret_val = hw->phy.ops.read_reg_locked(hw, BM_CS_STATUS, 9594edd8523SJack F Vogel &status_reg); 9604edd8523SJack F Vogel if (ret_val) 9614edd8523SJack F Vogel goto release; 9624edd8523SJack F Vogel 9634edd8523SJack F Vogel status_reg &= BM_CS_STATUS_LINK_UP | 9644edd8523SJack F Vogel BM_CS_STATUS_RESOLVED | 9654edd8523SJack F Vogel BM_CS_STATUS_SPEED_MASK; 9664edd8523SJack F Vogel 9674edd8523SJack F Vogel if (status_reg == (BM_CS_STATUS_LINK_UP | 9684edd8523SJack F Vogel BM_CS_STATUS_RESOLVED | 9694edd8523SJack F Vogel BM_CS_STATUS_SPEED_1000)) 9704edd8523SJack F Vogel k1_enable = FALSE; 9714edd8523SJack F Vogel } 9724edd8523SJack F Vogel 9734edd8523SJack F Vogel if (hw->phy.type == e1000_phy_82577) { 9744edd8523SJack F Vogel ret_val = hw->phy.ops.read_reg_locked(hw, HV_M_STATUS, 9754edd8523SJack F Vogel &status_reg); 9764edd8523SJack F Vogel if (ret_val) 9774edd8523SJack F Vogel goto release; 9784edd8523SJack F Vogel 9794edd8523SJack F Vogel status_reg &= HV_M_STATUS_LINK_UP | 9804edd8523SJack F Vogel HV_M_STATUS_AUTONEG_COMPLETE | 9814edd8523SJack F Vogel HV_M_STATUS_SPEED_MASK; 9824edd8523SJack F Vogel 9834edd8523SJack F Vogel if (status_reg == (HV_M_STATUS_LINK_UP | 9844edd8523SJack F Vogel HV_M_STATUS_AUTONEG_COMPLETE | 9854edd8523SJack F Vogel HV_M_STATUS_SPEED_1000)) 9864edd8523SJack F Vogel k1_enable = FALSE; 9874edd8523SJack F Vogel } 9884edd8523SJack F Vogel 9894edd8523SJack F Vogel /* Link stall fix for link up */ 9904edd8523SJack F Vogel ret_val = hw->phy.ops.write_reg_locked(hw, PHY_REG(770, 19), 9914edd8523SJack F Vogel 0x0100); 9924edd8523SJack F Vogel if (ret_val) 9934edd8523SJack F Vogel goto release; 9944edd8523SJack F Vogel 9954edd8523SJack F Vogel } else { 9964edd8523SJack F Vogel /* Link stall fix for link down */ 9974edd8523SJack F Vogel ret_val = hw->phy.ops.write_reg_locked(hw, PHY_REG(770, 19), 9984edd8523SJack F Vogel 0x4100); 9994edd8523SJack F Vogel if (ret_val) 10004edd8523SJack F Vogel goto release; 10014edd8523SJack F Vogel } 10024edd8523SJack F Vogel 10034edd8523SJack F Vogel ret_val = e1000_configure_k1_ich8lan(hw, k1_enable); 10044edd8523SJack F Vogel 10054edd8523SJack F Vogel release: 10064edd8523SJack F Vogel hw->phy.ops.release(hw); 10074edd8523SJack F Vogel out: 10084edd8523SJack F Vogel return ret_val; 10094edd8523SJack F Vogel } 10104edd8523SJack F Vogel 10114edd8523SJack F Vogel /** 10124edd8523SJack F Vogel * e1000_configure_k1_ich8lan - Configure K1 power state 10134edd8523SJack F Vogel * @hw: pointer to the HW structure 10144edd8523SJack F Vogel * @enable: K1 state to configure 10154edd8523SJack F Vogel * 10164edd8523SJack F Vogel * Configure the K1 power state based on the provided parameter. 10174edd8523SJack F Vogel * Assumes semaphore already acquired. 10184edd8523SJack F Vogel * 10194edd8523SJack F Vogel * Success returns 0, Failure returns -E1000_ERR_PHY (-2) 10204edd8523SJack F Vogel **/ 10214edd8523SJack F Vogel s32 e1000_configure_k1_ich8lan(struct e1000_hw *hw, bool k1_enable) 10224edd8523SJack F Vogel { 10234edd8523SJack F Vogel s32 ret_val = E1000_SUCCESS; 10244edd8523SJack F Vogel u32 ctrl_reg = 0; 10254edd8523SJack F Vogel u32 ctrl_ext = 0; 10264edd8523SJack F Vogel u32 reg = 0; 10274edd8523SJack F Vogel u16 kmrn_reg = 0; 10284edd8523SJack F Vogel 10294edd8523SJack F Vogel ret_val = e1000_read_kmrn_reg_locked(hw, 10304edd8523SJack F Vogel E1000_KMRNCTRLSTA_K1_CONFIG, 10314edd8523SJack F Vogel &kmrn_reg); 10324edd8523SJack F Vogel if (ret_val) 10334edd8523SJack F Vogel goto out; 10344edd8523SJack F Vogel 10354edd8523SJack F Vogel if (k1_enable) 10364edd8523SJack F Vogel kmrn_reg |= E1000_KMRNCTRLSTA_K1_ENABLE; 10374edd8523SJack F Vogel else 10384edd8523SJack F Vogel kmrn_reg &= ~E1000_KMRNCTRLSTA_K1_ENABLE; 10394edd8523SJack F Vogel 10404edd8523SJack F Vogel ret_val = e1000_write_kmrn_reg_locked(hw, 10414edd8523SJack F Vogel E1000_KMRNCTRLSTA_K1_CONFIG, 10424edd8523SJack F Vogel kmrn_reg); 10434edd8523SJack F Vogel if (ret_val) 10444edd8523SJack F Vogel goto out; 10454edd8523SJack F Vogel 10464edd8523SJack F Vogel usec_delay(20); 10474edd8523SJack F Vogel ctrl_ext = E1000_READ_REG(hw, E1000_CTRL_EXT); 10484edd8523SJack F Vogel ctrl_reg = E1000_READ_REG(hw, E1000_CTRL); 10494edd8523SJack F Vogel 10504edd8523SJack F Vogel reg = ctrl_reg & ~(E1000_CTRL_SPD_1000 | E1000_CTRL_SPD_100); 10514edd8523SJack F Vogel reg |= E1000_CTRL_FRCSPD; 10524edd8523SJack F Vogel E1000_WRITE_REG(hw, E1000_CTRL, reg); 10534edd8523SJack F Vogel 10544edd8523SJack F Vogel E1000_WRITE_REG(hw, E1000_CTRL_EXT, ctrl_ext | E1000_CTRL_EXT_SPD_BYPS); 10554edd8523SJack F Vogel usec_delay(20); 10564edd8523SJack F Vogel E1000_WRITE_REG(hw, E1000_CTRL, ctrl_reg); 10574edd8523SJack F Vogel E1000_WRITE_REG(hw, E1000_CTRL_EXT, ctrl_ext); 10584edd8523SJack F Vogel usec_delay(20); 10594edd8523SJack F Vogel 10604edd8523SJack F Vogel out: 10614edd8523SJack F Vogel return ret_val; 10624edd8523SJack F Vogel } 10634edd8523SJack F Vogel 10644edd8523SJack F Vogel /** 10654edd8523SJack F Vogel * e1000_oem_bits_config_ich8lan - SW-based LCD Configuration 10664edd8523SJack F Vogel * @hw: pointer to the HW structure 10674edd8523SJack F Vogel * @d0_state: boolean if entering d0 or d3 device state 10684edd8523SJack F Vogel * 10694edd8523SJack F Vogel * SW will configure Gbe Disable and LPLU based on the NVM. The four bits are 10704edd8523SJack F Vogel * collectively called OEM bits. The OEM Write Enable bit and SW Config bit 10714edd8523SJack F Vogel * in NVM determines whether HW should configure LPLU and Gbe Disable. 10724edd8523SJack F Vogel **/ 10734edd8523SJack F Vogel s32 e1000_oem_bits_config_ich8lan(struct e1000_hw *hw, bool d0_state) 10744edd8523SJack F Vogel { 10754edd8523SJack F Vogel s32 ret_val = 0; 10764edd8523SJack F Vogel u32 mac_reg; 10774edd8523SJack F Vogel u16 oem_reg; 10784edd8523SJack F Vogel 10794edd8523SJack F Vogel if (hw->mac.type != e1000_pchlan) 10804edd8523SJack F Vogel return ret_val; 10814edd8523SJack F Vogel 10824edd8523SJack F Vogel ret_val = hw->phy.ops.acquire(hw); 10834edd8523SJack F Vogel if (ret_val) 10844edd8523SJack F Vogel return ret_val; 10854edd8523SJack F Vogel 10864edd8523SJack F Vogel mac_reg = E1000_READ_REG(hw, E1000_EXTCNF_CTRL); 10874edd8523SJack F Vogel if (mac_reg & E1000_EXTCNF_CTRL_OEM_WRITE_ENABLE) 10884edd8523SJack F Vogel goto out; 10894edd8523SJack F Vogel 10904edd8523SJack F Vogel mac_reg = E1000_READ_REG(hw, E1000_FEXTNVM); 10914edd8523SJack F Vogel if (!(mac_reg & E1000_FEXTNVM_SW_CONFIG_ICH8M)) 10924edd8523SJack F Vogel goto out; 10934edd8523SJack F Vogel 10944edd8523SJack F Vogel mac_reg = E1000_READ_REG(hw, E1000_PHY_CTRL); 10954edd8523SJack F Vogel 10964edd8523SJack F Vogel ret_val = hw->phy.ops.read_reg_locked(hw, HV_OEM_BITS, &oem_reg); 10974edd8523SJack F Vogel if (ret_val) 10984edd8523SJack F Vogel goto out; 10994edd8523SJack F Vogel 11004edd8523SJack F Vogel oem_reg &= ~(HV_OEM_BITS_GBE_DIS | HV_OEM_BITS_LPLU); 11014edd8523SJack F Vogel 11024edd8523SJack F Vogel if (d0_state) { 11034edd8523SJack F Vogel if (mac_reg & E1000_PHY_CTRL_GBE_DISABLE) 11044edd8523SJack F Vogel oem_reg |= HV_OEM_BITS_GBE_DIS; 11054edd8523SJack F Vogel 11064edd8523SJack F Vogel if (mac_reg & E1000_PHY_CTRL_D0A_LPLU) 11074edd8523SJack F Vogel oem_reg |= HV_OEM_BITS_LPLU; 11084edd8523SJack F Vogel } else { 11094edd8523SJack F Vogel if (mac_reg & E1000_PHY_CTRL_NOND0A_GBE_DISABLE) 11104edd8523SJack F Vogel oem_reg |= HV_OEM_BITS_GBE_DIS; 11114edd8523SJack F Vogel 11124edd8523SJack F Vogel if (mac_reg & E1000_PHY_CTRL_NOND0A_LPLU) 11134edd8523SJack F Vogel oem_reg |= HV_OEM_BITS_LPLU; 11144edd8523SJack F Vogel } 11154edd8523SJack F Vogel /* Restart auto-neg to activate the bits */ 11164edd8523SJack F Vogel if (!hw->phy.ops.check_reset_block(hw)) 11174edd8523SJack F Vogel oem_reg |= HV_OEM_BITS_RESTART_AN; 11184edd8523SJack F Vogel ret_val = hw->phy.ops.write_reg_locked(hw, HV_OEM_BITS, oem_reg); 11194edd8523SJack F Vogel 11204edd8523SJack F Vogel out: 11214edd8523SJack F Vogel hw->phy.ops.release(hw); 11224edd8523SJack F Vogel 11234edd8523SJack F Vogel return ret_val; 11244edd8523SJack F Vogel } 11254edd8523SJack F Vogel 11264edd8523SJack F Vogel 11274edd8523SJack F Vogel /** 11289d81738fSJack F Vogel * e1000_hv_phy_powerdown_workaround_ich8lan - Power down workaround on Sx 11299d81738fSJack F Vogel * @hw: pointer to the HW structure 11309d81738fSJack F Vogel **/ 11319d81738fSJack F Vogel s32 e1000_hv_phy_powerdown_workaround_ich8lan(struct e1000_hw *hw) 11329d81738fSJack F Vogel { 11339d81738fSJack F Vogel if ((hw->phy.type != e1000_phy_82577) || (hw->revision_id > 2)) 11349d81738fSJack F Vogel return E1000_SUCCESS; 11359d81738fSJack F Vogel 11369d81738fSJack F Vogel return hw->phy.ops.write_reg(hw, PHY_REG(768, 25), 0x0444); 11379d81738fSJack F Vogel } 11389d81738fSJack F Vogel 11399d81738fSJack F Vogel /** 1140a69ed8dfSJack F Vogel * e1000_set_mdio_slow_mode_hv - Set slow MDIO access mode 1141a69ed8dfSJack F Vogel * @hw: pointer to the HW structure 1142a69ed8dfSJack F Vogel **/ 1143a69ed8dfSJack F Vogel static s32 e1000_set_mdio_slow_mode_hv(struct e1000_hw *hw) 1144a69ed8dfSJack F Vogel { 1145a69ed8dfSJack F Vogel s32 ret_val; 1146a69ed8dfSJack F Vogel u16 data; 1147a69ed8dfSJack F Vogel 1148a69ed8dfSJack F Vogel ret_val = hw->phy.ops.read_reg(hw, HV_KMRN_MODE_CTRL, &data); 1149a69ed8dfSJack F Vogel if (ret_val) 1150a69ed8dfSJack F Vogel return ret_val; 1151a69ed8dfSJack F Vogel 1152a69ed8dfSJack F Vogel data |= HV_KMRN_MDIO_SLOW; 1153a69ed8dfSJack F Vogel 1154a69ed8dfSJack F Vogel ret_val = hw->phy.ops.write_reg(hw, HV_KMRN_MODE_CTRL, data); 1155a69ed8dfSJack F Vogel 1156a69ed8dfSJack F Vogel return ret_val; 1157a69ed8dfSJack F Vogel } 1158a69ed8dfSJack F Vogel 1159a69ed8dfSJack F Vogel /** 11609d81738fSJack F Vogel * e1000_hv_phy_workarounds_ich8lan - A series of Phy workarounds to be 11619d81738fSJack F Vogel * done after every PHY reset. 11629d81738fSJack F Vogel **/ 11639d81738fSJack F Vogel static s32 e1000_hv_phy_workarounds_ich8lan(struct e1000_hw *hw) 11649d81738fSJack F Vogel { 11659d81738fSJack F Vogel s32 ret_val = E1000_SUCCESS; 1166a69ed8dfSJack F Vogel u16 phy_data; 11679d81738fSJack F Vogel 11689d81738fSJack F Vogel if (hw->mac.type != e1000_pchlan) 11694edd8523SJack F Vogel goto out; 11709d81738fSJack F Vogel 1171a69ed8dfSJack F Vogel /* Set MDIO slow mode before any other MDIO access */ 1172a69ed8dfSJack F Vogel if (hw->phy.type == e1000_phy_82577) { 1173a69ed8dfSJack F Vogel ret_val = e1000_set_mdio_slow_mode_hv(hw); 1174a69ed8dfSJack F Vogel if (ret_val) 1175a69ed8dfSJack F Vogel goto out; 1176a69ed8dfSJack F Vogel } 1177a69ed8dfSJack F Vogel 11789d81738fSJack F Vogel /* Hanksville M Phy init for IEEE. */ 11799d81738fSJack F Vogel if ((hw->revision_id == 2) && 11809d81738fSJack F Vogel (hw->phy.type == e1000_phy_82577) && 11819d81738fSJack F Vogel ((hw->phy.revision == 2) || (hw->phy.revision == 3))) { 11829d81738fSJack F Vogel hw->phy.ops.write_reg(hw, 0x10, 0x8823); 11839d81738fSJack F Vogel hw->phy.ops.write_reg(hw, 0x11, 0x0018); 11849d81738fSJack F Vogel hw->phy.ops.write_reg(hw, 0x10, 0x8824); 11859d81738fSJack F Vogel hw->phy.ops.write_reg(hw, 0x11, 0x0016); 11869d81738fSJack F Vogel hw->phy.ops.write_reg(hw, 0x10, 0x8825); 11879d81738fSJack F Vogel hw->phy.ops.write_reg(hw, 0x11, 0x001A); 11889d81738fSJack F Vogel hw->phy.ops.write_reg(hw, 0x10, 0x888C); 11899d81738fSJack F Vogel hw->phy.ops.write_reg(hw, 0x11, 0x0007); 11909d81738fSJack F Vogel hw->phy.ops.write_reg(hw, 0x10, 0x888D); 11919d81738fSJack F Vogel hw->phy.ops.write_reg(hw, 0x11, 0x0007); 11929d81738fSJack F Vogel hw->phy.ops.write_reg(hw, 0x10, 0x888E); 11939d81738fSJack F Vogel hw->phy.ops.write_reg(hw, 0x11, 0x0007); 11949d81738fSJack F Vogel hw->phy.ops.write_reg(hw, 0x10, 0x8827); 11959d81738fSJack F Vogel hw->phy.ops.write_reg(hw, 0x11, 0x0001); 11969d81738fSJack F Vogel hw->phy.ops.write_reg(hw, 0x10, 0x8835); 11979d81738fSJack F Vogel hw->phy.ops.write_reg(hw, 0x11, 0x0001); 11989d81738fSJack F Vogel hw->phy.ops.write_reg(hw, 0x10, 0x8834); 11999d81738fSJack F Vogel hw->phy.ops.write_reg(hw, 0x11, 0x0001); 12009d81738fSJack F Vogel hw->phy.ops.write_reg(hw, 0x10, 0x8833); 12019d81738fSJack F Vogel hw->phy.ops.write_reg(hw, 0x11, 0x0002); 12029d81738fSJack F Vogel } 12039d81738fSJack F Vogel 12049d81738fSJack F Vogel if (((hw->phy.type == e1000_phy_82577) && 12059d81738fSJack F Vogel ((hw->phy.revision == 1) || (hw->phy.revision == 2))) || 12069d81738fSJack F Vogel ((hw->phy.type == e1000_phy_82578) && (hw->phy.revision == 1))) { 12079d81738fSJack F Vogel /* Disable generation of early preamble */ 12089d81738fSJack F Vogel ret_val = hw->phy.ops.write_reg(hw, PHY_REG(769, 25), 0x4431); 12099d81738fSJack F Vogel if (ret_val) 12104edd8523SJack F Vogel goto out; 12119d81738fSJack F Vogel 12129d81738fSJack F Vogel /* Preamble tuning for SSC */ 12139d81738fSJack F Vogel ret_val = hw->phy.ops.write_reg(hw, PHY_REG(770, 16), 0xA204); 12149d81738fSJack F Vogel if (ret_val) 12154edd8523SJack F Vogel goto out; 12169d81738fSJack F Vogel } 12179d81738fSJack F Vogel 12189d81738fSJack F Vogel if (hw->phy.type == e1000_phy_82578) { 12199d81738fSJack F Vogel if (hw->revision_id < 3) { 12209d81738fSJack F Vogel /* PHY config */ 12219d81738fSJack F Vogel ret_val = hw->phy.ops.write_reg(hw, (1 << 6) | 0x29, 12229d81738fSJack F Vogel 0x66C0); 12239d81738fSJack F Vogel if (ret_val) 12244edd8523SJack F Vogel goto out; 12259d81738fSJack F Vogel 12269d81738fSJack F Vogel /* PHY config */ 12279d81738fSJack F Vogel ret_val = hw->phy.ops.write_reg(hw, (1 << 6) | 0x1E, 12289d81738fSJack F Vogel 0xFFFF); 12299d81738fSJack F Vogel if (ret_val) 12304edd8523SJack F Vogel goto out; 12319d81738fSJack F Vogel } 12329d81738fSJack F Vogel 12339d81738fSJack F Vogel /* 12349d81738fSJack F Vogel * Return registers to default by doing a soft reset then 12359d81738fSJack F Vogel * writing 0x3140 to the control register. 12369d81738fSJack F Vogel */ 12379d81738fSJack F Vogel if (hw->phy.revision < 2) { 12389d81738fSJack F Vogel e1000_phy_sw_reset_generic(hw); 12399d81738fSJack F Vogel ret_val = hw->phy.ops.write_reg(hw, PHY_CONTROL, 12409d81738fSJack F Vogel 0x3140); 12419d81738fSJack F Vogel } 12429d81738fSJack F Vogel } 12439d81738fSJack F Vogel 12449d81738fSJack F Vogel if ((hw->revision_id == 2) && 12459d81738fSJack F Vogel (hw->phy.type == e1000_phy_82577) && 12469d81738fSJack F Vogel ((hw->phy.revision == 2) || (hw->phy.revision == 3))) { 12479d81738fSJack F Vogel /* 12489d81738fSJack F Vogel * Workaround for OEM (GbE) not operating after reset - 12499d81738fSJack F Vogel * restart AN (twice) 12509d81738fSJack F Vogel */ 12519d81738fSJack F Vogel ret_val = hw->phy.ops.write_reg(hw, PHY_REG(768, 25), 0x0400); 12529d81738fSJack F Vogel if (ret_val) 12534edd8523SJack F Vogel goto out; 12549d81738fSJack F Vogel ret_val = hw->phy.ops.write_reg(hw, PHY_REG(768, 25), 0x0400); 12559d81738fSJack F Vogel if (ret_val) 12564edd8523SJack F Vogel goto out; 12579d81738fSJack F Vogel } 12589d81738fSJack F Vogel 12599d81738fSJack F Vogel /* Select page 0 */ 12609d81738fSJack F Vogel ret_val = hw->phy.ops.acquire(hw); 12619d81738fSJack F Vogel if (ret_val) 12624edd8523SJack F Vogel goto out; 12634edd8523SJack F Vogel 12649d81738fSJack F Vogel hw->phy.addr = 1; 12654edd8523SJack F Vogel ret_val = e1000_write_phy_reg_mdic(hw, IGP01E1000_PHY_PAGE_SELECT, 0); 1266a69ed8dfSJack F Vogel hw->phy.ops.release(hw); 12674edd8523SJack F Vogel if (ret_val) 12684edd8523SJack F Vogel goto out; 12699d81738fSJack F Vogel 12704edd8523SJack F Vogel /* 12714edd8523SJack F Vogel * Configure the K1 Si workaround during phy reset assuming there is 12724edd8523SJack F Vogel * link so that it disables K1 if link is in 1Gbps. 12734edd8523SJack F Vogel */ 12744edd8523SJack F Vogel ret_val = e1000_k1_gig_workaround_hv(hw, TRUE); 1275a69ed8dfSJack F Vogel if (ret_val) 1276a69ed8dfSJack F Vogel goto out; 12774edd8523SJack F Vogel 1278a69ed8dfSJack F Vogel /* Workaround for link disconnects on a busy hub in half duplex */ 1279a69ed8dfSJack F Vogel ret_val = hw->phy.ops.acquire(hw); 1280a69ed8dfSJack F Vogel if (ret_val) 1281a69ed8dfSJack F Vogel goto out; 1282a69ed8dfSJack F Vogel ret_val = hw->phy.ops.read_reg_locked(hw, 1283a69ed8dfSJack F Vogel PHY_REG(BM_PORT_CTRL_PAGE, 17), 1284a69ed8dfSJack F Vogel &phy_data); 1285a69ed8dfSJack F Vogel if (ret_val) 1286a69ed8dfSJack F Vogel goto release; 1287a69ed8dfSJack F Vogel ret_val = hw->phy.ops.write_reg_locked(hw, 1288a69ed8dfSJack F Vogel PHY_REG(BM_PORT_CTRL_PAGE, 17), 1289a69ed8dfSJack F Vogel phy_data & 0x00FF); 1290a69ed8dfSJack F Vogel release: 1291a69ed8dfSJack F Vogel hw->phy.ops.release(hw); 12924edd8523SJack F Vogel out: 12939d81738fSJack F Vogel return ret_val; 12949d81738fSJack F Vogel } 12959d81738fSJack F Vogel 12969d81738fSJack F Vogel /** 12979d81738fSJack F Vogel * e1000_lan_init_done_ich8lan - Check for PHY config completion 12988cfa0ad2SJack F Vogel * @hw: pointer to the HW structure 12998cfa0ad2SJack F Vogel * 13009d81738fSJack F Vogel * Check the appropriate indication the MAC has finished configuring the 13019d81738fSJack F Vogel * PHY after a software reset. 13028cfa0ad2SJack F Vogel **/ 13039d81738fSJack F Vogel static void e1000_lan_init_done_ich8lan(struct e1000_hw *hw) 13048cfa0ad2SJack F Vogel { 13059d81738fSJack F Vogel u32 data, loop = E1000_ICH8_LAN_INIT_TIMEOUT; 13068cfa0ad2SJack F Vogel 13079d81738fSJack F Vogel DEBUGFUNC("e1000_lan_init_done_ich8lan"); 13088cfa0ad2SJack F Vogel 13099d81738fSJack F Vogel /* Wait for basic configuration completes before proceeding */ 13109d81738fSJack F Vogel do { 13119d81738fSJack F Vogel data = E1000_READ_REG(hw, E1000_STATUS); 13129d81738fSJack F Vogel data &= E1000_STATUS_LAN_INIT_DONE; 13139d81738fSJack F Vogel usec_delay(100); 13149d81738fSJack F Vogel } while ((!data) && --loop); 13158cfa0ad2SJack F Vogel 13169d81738fSJack F Vogel /* 13179d81738fSJack F Vogel * If basic configuration is incomplete before the above loop 13189d81738fSJack F Vogel * count reaches 0, loading the configuration from NVM will 13199d81738fSJack F Vogel * leave the PHY in a bad state possibly resulting in no link. 13209d81738fSJack F Vogel */ 13219d81738fSJack F Vogel if (loop == 0) 13229d81738fSJack F Vogel DEBUGOUT("LAN_INIT_DONE not set, increase timeout\n"); 13238cfa0ad2SJack F Vogel 13249d81738fSJack F Vogel /* Clear the Init Done bit for the next init event */ 13259d81738fSJack F Vogel data = E1000_READ_REG(hw, E1000_STATUS); 13269d81738fSJack F Vogel data &= ~E1000_STATUS_LAN_INIT_DONE; 13279d81738fSJack F Vogel E1000_WRITE_REG(hw, E1000_STATUS, data); 13288cfa0ad2SJack F Vogel } 13298cfa0ad2SJack F Vogel 13308cfa0ad2SJack F Vogel /** 13318cfa0ad2SJack F Vogel * e1000_phy_hw_reset_ich8lan - Performs a PHY reset 13328cfa0ad2SJack F Vogel * @hw: pointer to the HW structure 13338cfa0ad2SJack F Vogel * 13348cfa0ad2SJack F Vogel * Resets the PHY 13358cfa0ad2SJack F Vogel * This is a function pointer entry point called by drivers 13368cfa0ad2SJack F Vogel * or other shared routines. 13378cfa0ad2SJack F Vogel **/ 13388cfa0ad2SJack F Vogel static s32 e1000_phy_hw_reset_ich8lan(struct e1000_hw *hw) 13398cfa0ad2SJack F Vogel { 13404edd8523SJack F Vogel s32 ret_val = E1000_SUCCESS; 13414edd8523SJack F Vogel u16 reg; 13428cfa0ad2SJack F Vogel 13438cfa0ad2SJack F Vogel DEBUGFUNC("e1000_phy_hw_reset_ich8lan"); 13448cfa0ad2SJack F Vogel 13458cfa0ad2SJack F Vogel ret_val = e1000_phy_hw_reset_generic(hw); 13468cfa0ad2SJack F Vogel if (ret_val) 13478cfa0ad2SJack F Vogel goto out; 13488cfa0ad2SJack F Vogel 13499d81738fSJack F Vogel /* Allow time for h/w to get to a quiescent state after reset */ 13509d81738fSJack F Vogel msec_delay(10); 13519d81738fSJack F Vogel 1352a69ed8dfSJack F Vogel /* Perform any necessary post-reset workarounds */ 1353a69ed8dfSJack F Vogel switch (hw->mac.type) { 1354a69ed8dfSJack F Vogel case e1000_pchlan: 13559d81738fSJack F Vogel ret_val = e1000_hv_phy_workarounds_ich8lan(hw); 13569d81738fSJack F Vogel if (ret_val) 13579d81738fSJack F Vogel goto out; 1358a69ed8dfSJack F Vogel break; 1359a69ed8dfSJack F Vogel default: 1360a69ed8dfSJack F Vogel break; 13619d81738fSJack F Vogel } 13629d81738fSJack F Vogel 13634edd8523SJack F Vogel /* Dummy read to clear the phy wakeup bit after lcd reset */ 13644edd8523SJack F Vogel if (hw->mac.type == e1000_pchlan) 13654edd8523SJack F Vogel hw->phy.ops.read_reg(hw, BM_WUC, ®); 13668cfa0ad2SJack F Vogel 13674edd8523SJack F Vogel /* Configure the LCD with the extended configuration region in NVM */ 13684edd8523SJack F Vogel ret_val = e1000_sw_lcd_config_ich8lan(hw); 13698cfa0ad2SJack F Vogel if (ret_val) 13708cfa0ad2SJack F Vogel goto out; 13718cfa0ad2SJack F Vogel 13724edd8523SJack F Vogel /* Configure the LCD with the OEM bits in NVM */ 13734edd8523SJack F Vogel ret_val = e1000_oem_bits_config_ich8lan(hw, TRUE); 13748cfa0ad2SJack F Vogel 13758cfa0ad2SJack F Vogel out: 13768cfa0ad2SJack F Vogel return ret_val; 13778cfa0ad2SJack F Vogel } 13788cfa0ad2SJack F Vogel 13798cfa0ad2SJack F Vogel /** 13804edd8523SJack F Vogel * e1000_set_lplu_state_pchlan - Set Low Power Link Up state 13818cfa0ad2SJack F Vogel * @hw: pointer to the HW structure 13824edd8523SJack F Vogel * @active: TRUE to enable LPLU, FALSE to disable 13838cfa0ad2SJack F Vogel * 13844edd8523SJack F Vogel * Sets the LPLU state according to the active flag. For PCH, if OEM write 13854edd8523SJack F Vogel * bit are disabled in the NVM, writing the LPLU bits in the MAC will not set 13864edd8523SJack F Vogel * the phy speed. This function will manually set the LPLU bit and restart 13874edd8523SJack F Vogel * auto-neg as hw would do. D3 and D0 LPLU will call the same function 13884edd8523SJack F Vogel * since it configures the same bit. 13898cfa0ad2SJack F Vogel **/ 13904edd8523SJack F Vogel static s32 e1000_set_lplu_state_pchlan(struct e1000_hw *hw, bool active) 13918cfa0ad2SJack F Vogel { 13924edd8523SJack F Vogel s32 ret_val = E1000_SUCCESS; 13934edd8523SJack F Vogel u16 oem_reg; 13948cfa0ad2SJack F Vogel 13954edd8523SJack F Vogel DEBUGFUNC("e1000_set_lplu_state_pchlan"); 13968cfa0ad2SJack F Vogel 13974edd8523SJack F Vogel ret_val = hw->phy.ops.read_reg(hw, HV_OEM_BITS, &oem_reg); 13988cfa0ad2SJack F Vogel if (ret_val) 13998cfa0ad2SJack F Vogel goto out; 14008cfa0ad2SJack F Vogel 14014edd8523SJack F Vogel if (active) 14024edd8523SJack F Vogel oem_reg |= HV_OEM_BITS_LPLU; 14034edd8523SJack F Vogel else 14044edd8523SJack F Vogel oem_reg &= ~HV_OEM_BITS_LPLU; 14058cfa0ad2SJack F Vogel 14064edd8523SJack F Vogel oem_reg |= HV_OEM_BITS_RESTART_AN; 14074edd8523SJack F Vogel ret_val = hw->phy.ops.write_reg(hw, HV_OEM_BITS, oem_reg); 14088cfa0ad2SJack F Vogel 14098cfa0ad2SJack F Vogel out: 14108cfa0ad2SJack F Vogel return ret_val; 14118cfa0ad2SJack F Vogel } 14128cfa0ad2SJack F Vogel 14138cfa0ad2SJack F Vogel /** 14148cfa0ad2SJack F Vogel * e1000_set_d0_lplu_state_ich8lan - Set Low Power Linkup D0 state 14158cfa0ad2SJack F Vogel * @hw: pointer to the HW structure 14168cfa0ad2SJack F Vogel * @active: TRUE to enable LPLU, FALSE to disable 14178cfa0ad2SJack F Vogel * 14188cfa0ad2SJack F Vogel * Sets the LPLU D0 state according to the active flag. When 14198cfa0ad2SJack F Vogel * activating LPLU this function also disables smart speed 14208cfa0ad2SJack F Vogel * and vice versa. LPLU will not be activated unless the 14218cfa0ad2SJack F Vogel * device autonegotiation advertisement meets standards of 14228cfa0ad2SJack F Vogel * either 10 or 10/100 or 10/100/1000 at all duplexes. 14238cfa0ad2SJack F Vogel * This is a function pointer entry point only called by 14248cfa0ad2SJack F Vogel * PHY setup routines. 14258cfa0ad2SJack F Vogel **/ 1426daf9197cSJack F Vogel static s32 e1000_set_d0_lplu_state_ich8lan(struct e1000_hw *hw, bool active) 14278cfa0ad2SJack F Vogel { 14288cfa0ad2SJack F Vogel struct e1000_phy_info *phy = &hw->phy; 14298cfa0ad2SJack F Vogel u32 phy_ctrl; 14308cfa0ad2SJack F Vogel s32 ret_val = E1000_SUCCESS; 14318cfa0ad2SJack F Vogel u16 data; 14328cfa0ad2SJack F Vogel 14338cfa0ad2SJack F Vogel DEBUGFUNC("e1000_set_d0_lplu_state_ich8lan"); 14348cfa0ad2SJack F Vogel 14358cfa0ad2SJack F Vogel if (phy->type == e1000_phy_ife) 14368cfa0ad2SJack F Vogel goto out; 14378cfa0ad2SJack F Vogel 14388cfa0ad2SJack F Vogel phy_ctrl = E1000_READ_REG(hw, E1000_PHY_CTRL); 14398cfa0ad2SJack F Vogel 14408cfa0ad2SJack F Vogel if (active) { 14418cfa0ad2SJack F Vogel phy_ctrl |= E1000_PHY_CTRL_D0A_LPLU; 14428cfa0ad2SJack F Vogel E1000_WRITE_REG(hw, E1000_PHY_CTRL, phy_ctrl); 14438cfa0ad2SJack F Vogel 14449d81738fSJack F Vogel if (phy->type != e1000_phy_igp_3) 14459d81738fSJack F Vogel goto out; 14469d81738fSJack F Vogel 14478cfa0ad2SJack F Vogel /* 14488cfa0ad2SJack F Vogel * Call gig speed drop workaround on LPLU before accessing 14498cfa0ad2SJack F Vogel * any PHY registers 14508cfa0ad2SJack F Vogel */ 14519d81738fSJack F Vogel if (hw->mac.type == e1000_ich8lan) 14528cfa0ad2SJack F Vogel e1000_gig_downshift_workaround_ich8lan(hw); 14538cfa0ad2SJack F Vogel 14548cfa0ad2SJack F Vogel /* When LPLU is enabled, we should disable SmartSpeed */ 14558cfa0ad2SJack F Vogel ret_val = phy->ops.read_reg(hw, 14568cfa0ad2SJack F Vogel IGP01E1000_PHY_PORT_CONFIG, 14578cfa0ad2SJack F Vogel &data); 14588cfa0ad2SJack F Vogel data &= ~IGP01E1000_PSCFR_SMART_SPEED; 14598cfa0ad2SJack F Vogel ret_val = phy->ops.write_reg(hw, 14608cfa0ad2SJack F Vogel IGP01E1000_PHY_PORT_CONFIG, 14618cfa0ad2SJack F Vogel data); 14628cfa0ad2SJack F Vogel if (ret_val) 14638cfa0ad2SJack F Vogel goto out; 14648cfa0ad2SJack F Vogel } else { 14658cfa0ad2SJack F Vogel phy_ctrl &= ~E1000_PHY_CTRL_D0A_LPLU; 14668cfa0ad2SJack F Vogel E1000_WRITE_REG(hw, E1000_PHY_CTRL, phy_ctrl); 14678cfa0ad2SJack F Vogel 14689d81738fSJack F Vogel if (phy->type != e1000_phy_igp_3) 14699d81738fSJack F Vogel goto out; 14709d81738fSJack F Vogel 14718cfa0ad2SJack F Vogel /* 14728cfa0ad2SJack F Vogel * LPLU and SmartSpeed are mutually exclusive. LPLU is used 14738cfa0ad2SJack F Vogel * during Dx states where the power conservation is most 14748cfa0ad2SJack F Vogel * important. During driver activity we should enable 14758cfa0ad2SJack F Vogel * SmartSpeed, so performance is maintained. 14768cfa0ad2SJack F Vogel */ 14778cfa0ad2SJack F Vogel if (phy->smart_speed == e1000_smart_speed_on) { 14788cfa0ad2SJack F Vogel ret_val = phy->ops.read_reg(hw, 14798cfa0ad2SJack F Vogel IGP01E1000_PHY_PORT_CONFIG, 14808cfa0ad2SJack F Vogel &data); 14818cfa0ad2SJack F Vogel if (ret_val) 14828cfa0ad2SJack F Vogel goto out; 14838cfa0ad2SJack F Vogel 14848cfa0ad2SJack F Vogel data |= IGP01E1000_PSCFR_SMART_SPEED; 14858cfa0ad2SJack F Vogel ret_val = phy->ops.write_reg(hw, 14868cfa0ad2SJack F Vogel IGP01E1000_PHY_PORT_CONFIG, 14878cfa0ad2SJack F Vogel data); 14888cfa0ad2SJack F Vogel if (ret_val) 14898cfa0ad2SJack F Vogel goto out; 14908cfa0ad2SJack F Vogel } else if (phy->smart_speed == e1000_smart_speed_off) { 14918cfa0ad2SJack F Vogel ret_val = phy->ops.read_reg(hw, 14928cfa0ad2SJack F Vogel IGP01E1000_PHY_PORT_CONFIG, 14938cfa0ad2SJack F Vogel &data); 14948cfa0ad2SJack F Vogel if (ret_val) 14958cfa0ad2SJack F Vogel goto out; 14968cfa0ad2SJack F Vogel 14978cfa0ad2SJack F Vogel data &= ~IGP01E1000_PSCFR_SMART_SPEED; 14988cfa0ad2SJack F Vogel ret_val = phy->ops.write_reg(hw, 14998cfa0ad2SJack F Vogel IGP01E1000_PHY_PORT_CONFIG, 15008cfa0ad2SJack F Vogel data); 15018cfa0ad2SJack F Vogel if (ret_val) 15028cfa0ad2SJack F Vogel goto out; 15038cfa0ad2SJack F Vogel } 15048cfa0ad2SJack F Vogel } 15058cfa0ad2SJack F Vogel 15068cfa0ad2SJack F Vogel out: 15078cfa0ad2SJack F Vogel return ret_val; 15088cfa0ad2SJack F Vogel } 15098cfa0ad2SJack F Vogel 15108cfa0ad2SJack F Vogel /** 15118cfa0ad2SJack F Vogel * e1000_set_d3_lplu_state_ich8lan - Set Low Power Linkup D3 state 15128cfa0ad2SJack F Vogel * @hw: pointer to the HW structure 15138cfa0ad2SJack F Vogel * @active: TRUE to enable LPLU, FALSE to disable 15148cfa0ad2SJack F Vogel * 15158cfa0ad2SJack F Vogel * Sets the LPLU D3 state according to the active flag. When 15168cfa0ad2SJack F Vogel * activating LPLU this function also disables smart speed 15178cfa0ad2SJack F Vogel * and vice versa. LPLU will not be activated unless the 15188cfa0ad2SJack F Vogel * device autonegotiation advertisement meets standards of 15198cfa0ad2SJack F Vogel * either 10 or 10/100 or 10/100/1000 at all duplexes. 15208cfa0ad2SJack F Vogel * This is a function pointer entry point only called by 15218cfa0ad2SJack F Vogel * PHY setup routines. 15228cfa0ad2SJack F Vogel **/ 1523daf9197cSJack F Vogel static s32 e1000_set_d3_lplu_state_ich8lan(struct e1000_hw *hw, bool active) 15248cfa0ad2SJack F Vogel { 15258cfa0ad2SJack F Vogel struct e1000_phy_info *phy = &hw->phy; 15268cfa0ad2SJack F Vogel u32 phy_ctrl; 15278cfa0ad2SJack F Vogel s32 ret_val = E1000_SUCCESS; 15288cfa0ad2SJack F Vogel u16 data; 15298cfa0ad2SJack F Vogel 15308cfa0ad2SJack F Vogel DEBUGFUNC("e1000_set_d3_lplu_state_ich8lan"); 15318cfa0ad2SJack F Vogel 15328cfa0ad2SJack F Vogel phy_ctrl = E1000_READ_REG(hw, E1000_PHY_CTRL); 15338cfa0ad2SJack F Vogel 15348cfa0ad2SJack F Vogel if (!active) { 15358cfa0ad2SJack F Vogel phy_ctrl &= ~E1000_PHY_CTRL_NOND0A_LPLU; 15368cfa0ad2SJack F Vogel E1000_WRITE_REG(hw, E1000_PHY_CTRL, phy_ctrl); 15379d81738fSJack F Vogel 15389d81738fSJack F Vogel if (phy->type != e1000_phy_igp_3) 15399d81738fSJack F Vogel goto out; 15409d81738fSJack F Vogel 15418cfa0ad2SJack F Vogel /* 15428cfa0ad2SJack F Vogel * LPLU and SmartSpeed are mutually exclusive. LPLU is used 15438cfa0ad2SJack F Vogel * during Dx states where the power conservation is most 15448cfa0ad2SJack F Vogel * important. During driver activity we should enable 15458cfa0ad2SJack F Vogel * SmartSpeed, so performance is maintained. 15468cfa0ad2SJack F Vogel */ 15478cfa0ad2SJack F Vogel if (phy->smart_speed == e1000_smart_speed_on) { 15488cfa0ad2SJack F Vogel ret_val = phy->ops.read_reg(hw, 15498cfa0ad2SJack F Vogel IGP01E1000_PHY_PORT_CONFIG, 15508cfa0ad2SJack F Vogel &data); 15518cfa0ad2SJack F Vogel if (ret_val) 15528cfa0ad2SJack F Vogel goto out; 15538cfa0ad2SJack F Vogel 15548cfa0ad2SJack F Vogel data |= IGP01E1000_PSCFR_SMART_SPEED; 15558cfa0ad2SJack F Vogel ret_val = phy->ops.write_reg(hw, 15568cfa0ad2SJack F Vogel IGP01E1000_PHY_PORT_CONFIG, 15578cfa0ad2SJack F Vogel data); 15588cfa0ad2SJack F Vogel if (ret_val) 15598cfa0ad2SJack F Vogel goto out; 15608cfa0ad2SJack F Vogel } else if (phy->smart_speed == e1000_smart_speed_off) { 15618cfa0ad2SJack F Vogel ret_val = phy->ops.read_reg(hw, 15628cfa0ad2SJack F Vogel IGP01E1000_PHY_PORT_CONFIG, 15638cfa0ad2SJack F Vogel &data); 15648cfa0ad2SJack F Vogel if (ret_val) 15658cfa0ad2SJack F Vogel goto out; 15668cfa0ad2SJack F Vogel 15678cfa0ad2SJack F Vogel data &= ~IGP01E1000_PSCFR_SMART_SPEED; 15688cfa0ad2SJack F Vogel ret_val = phy->ops.write_reg(hw, 15698cfa0ad2SJack F Vogel IGP01E1000_PHY_PORT_CONFIG, 15708cfa0ad2SJack F Vogel data); 15718cfa0ad2SJack F Vogel if (ret_val) 15728cfa0ad2SJack F Vogel goto out; 15738cfa0ad2SJack F Vogel } 15748cfa0ad2SJack F Vogel } else if ((phy->autoneg_advertised == E1000_ALL_SPEED_DUPLEX) || 15758cfa0ad2SJack F Vogel (phy->autoneg_advertised == E1000_ALL_NOT_GIG) || 15768cfa0ad2SJack F Vogel (phy->autoneg_advertised == E1000_ALL_10_SPEED)) { 15778cfa0ad2SJack F Vogel phy_ctrl |= E1000_PHY_CTRL_NOND0A_LPLU; 15788cfa0ad2SJack F Vogel E1000_WRITE_REG(hw, E1000_PHY_CTRL, phy_ctrl); 15798cfa0ad2SJack F Vogel 15809d81738fSJack F Vogel if (phy->type != e1000_phy_igp_3) 15819d81738fSJack F Vogel goto out; 15829d81738fSJack F Vogel 15838cfa0ad2SJack F Vogel /* 15848cfa0ad2SJack F Vogel * Call gig speed drop workaround on LPLU before accessing 15858cfa0ad2SJack F Vogel * any PHY registers 15868cfa0ad2SJack F Vogel */ 15879d81738fSJack F Vogel if (hw->mac.type == e1000_ich8lan) 15888cfa0ad2SJack F Vogel e1000_gig_downshift_workaround_ich8lan(hw); 15898cfa0ad2SJack F Vogel 15908cfa0ad2SJack F Vogel /* When LPLU is enabled, we should disable SmartSpeed */ 15918cfa0ad2SJack F Vogel ret_val = phy->ops.read_reg(hw, 15928cfa0ad2SJack F Vogel IGP01E1000_PHY_PORT_CONFIG, 15938cfa0ad2SJack F Vogel &data); 15948cfa0ad2SJack F Vogel if (ret_val) 15958cfa0ad2SJack F Vogel goto out; 15968cfa0ad2SJack F Vogel 15978cfa0ad2SJack F Vogel data &= ~IGP01E1000_PSCFR_SMART_SPEED; 15988cfa0ad2SJack F Vogel ret_val = phy->ops.write_reg(hw, 15998cfa0ad2SJack F Vogel IGP01E1000_PHY_PORT_CONFIG, 16008cfa0ad2SJack F Vogel data); 16018cfa0ad2SJack F Vogel } 16028cfa0ad2SJack F Vogel 16038cfa0ad2SJack F Vogel out: 16048cfa0ad2SJack F Vogel return ret_val; 16058cfa0ad2SJack F Vogel } 16068cfa0ad2SJack F Vogel 16078cfa0ad2SJack F Vogel /** 16088cfa0ad2SJack F Vogel * e1000_valid_nvm_bank_detect_ich8lan - finds out the valid bank 0 or 1 16098cfa0ad2SJack F Vogel * @hw: pointer to the HW structure 16108cfa0ad2SJack F Vogel * @bank: pointer to the variable that returns the active bank 16118cfa0ad2SJack F Vogel * 16128cfa0ad2SJack F Vogel * Reads signature byte from the NVM using the flash access registers. 1613d035aa2dSJack F Vogel * Word 0x13 bits 15:14 = 10b indicate a valid signature for that bank. 16148cfa0ad2SJack F Vogel **/ 16158cfa0ad2SJack F Vogel static s32 e1000_valid_nvm_bank_detect_ich8lan(struct e1000_hw *hw, u32 *bank) 16168cfa0ad2SJack F Vogel { 1617d035aa2dSJack F Vogel u32 eecd; 16188cfa0ad2SJack F Vogel struct e1000_nvm_info *nvm = &hw->nvm; 16198cfa0ad2SJack F Vogel u32 bank1_offset = nvm->flash_bank_size * sizeof(u16); 16208cfa0ad2SJack F Vogel u32 act_offset = E1000_ICH_NVM_SIG_WORD * 2 + 1; 1621d035aa2dSJack F Vogel u8 sig_byte = 0; 1622d035aa2dSJack F Vogel s32 ret_val = E1000_SUCCESS; 16238cfa0ad2SJack F Vogel 1624d035aa2dSJack F Vogel switch (hw->mac.type) { 1625d035aa2dSJack F Vogel case e1000_ich8lan: 1626d035aa2dSJack F Vogel case e1000_ich9lan: 1627d035aa2dSJack F Vogel eecd = E1000_READ_REG(hw, E1000_EECD); 1628d035aa2dSJack F Vogel if ((eecd & E1000_EECD_SEC1VAL_VALID_MASK) == 1629d035aa2dSJack F Vogel E1000_EECD_SEC1VAL_VALID_MASK) { 1630d035aa2dSJack F Vogel if (eecd & E1000_EECD_SEC1VAL) 16318cfa0ad2SJack F Vogel *bank = 1; 16328cfa0ad2SJack F Vogel else 16338cfa0ad2SJack F Vogel *bank = 0; 1634d035aa2dSJack F Vogel 1635d035aa2dSJack F Vogel goto out; 1636d035aa2dSJack F Vogel } 1637d035aa2dSJack F Vogel DEBUGOUT("Unable to determine valid NVM bank via EEC - " 1638d035aa2dSJack F Vogel "reading flash signature\n"); 1639d035aa2dSJack F Vogel /* fall-thru */ 1640d035aa2dSJack F Vogel default: 1641d035aa2dSJack F Vogel /* set bank to 0 in case flash read fails */ 16428cfa0ad2SJack F Vogel *bank = 0; 16438cfa0ad2SJack F Vogel 1644d035aa2dSJack F Vogel /* Check bank 0 */ 1645d035aa2dSJack F Vogel ret_val = e1000_read_flash_byte_ich8lan(hw, act_offset, 1646d035aa2dSJack F Vogel &sig_byte); 1647d035aa2dSJack F Vogel if (ret_val) 1648d035aa2dSJack F Vogel goto out; 1649d035aa2dSJack F Vogel if ((sig_byte & E1000_ICH_NVM_VALID_SIG_MASK) == 1650d035aa2dSJack F Vogel E1000_ICH_NVM_SIG_VALUE) { 1651d035aa2dSJack F Vogel *bank = 0; 1652d035aa2dSJack F Vogel goto out; 1653d035aa2dSJack F Vogel } 1654d035aa2dSJack F Vogel 1655d035aa2dSJack F Vogel /* Check bank 1 */ 1656d035aa2dSJack F Vogel ret_val = e1000_read_flash_byte_ich8lan(hw, act_offset + 1657d035aa2dSJack F Vogel bank1_offset, 1658d035aa2dSJack F Vogel &sig_byte); 1659d035aa2dSJack F Vogel if (ret_val) 1660d035aa2dSJack F Vogel goto out; 1661d035aa2dSJack F Vogel if ((sig_byte & E1000_ICH_NVM_VALID_SIG_MASK) == 1662d035aa2dSJack F Vogel E1000_ICH_NVM_SIG_VALUE) { 16638cfa0ad2SJack F Vogel *bank = 1; 1664d035aa2dSJack F Vogel goto out; 16658cfa0ad2SJack F Vogel } 16668cfa0ad2SJack F Vogel 1667d035aa2dSJack F Vogel DEBUGOUT("ERROR: No valid NVM bank present\n"); 1668d035aa2dSJack F Vogel ret_val = -E1000_ERR_NVM; 1669d035aa2dSJack F Vogel break; 1670d035aa2dSJack F Vogel } 1671d035aa2dSJack F Vogel out: 16728cfa0ad2SJack F Vogel return ret_val; 16738cfa0ad2SJack F Vogel } 16748cfa0ad2SJack F Vogel 16758cfa0ad2SJack F Vogel /** 16768cfa0ad2SJack F Vogel * e1000_read_nvm_ich8lan - Read word(s) from the NVM 16778cfa0ad2SJack F Vogel * @hw: pointer to the HW structure 16788cfa0ad2SJack F Vogel * @offset: The offset (in bytes) of the word(s) to read. 16798cfa0ad2SJack F Vogel * @words: Size of data to read in words 16808cfa0ad2SJack F Vogel * @data: Pointer to the word(s) to read at offset. 16818cfa0ad2SJack F Vogel * 16828cfa0ad2SJack F Vogel * Reads a word(s) from the NVM using the flash access registers. 16838cfa0ad2SJack F Vogel **/ 16848cfa0ad2SJack F Vogel static s32 e1000_read_nvm_ich8lan(struct e1000_hw *hw, u16 offset, u16 words, 16858cfa0ad2SJack F Vogel u16 *data) 16868cfa0ad2SJack F Vogel { 16878cfa0ad2SJack F Vogel struct e1000_nvm_info *nvm = &hw->nvm; 1688daf9197cSJack F Vogel struct e1000_dev_spec_ich8lan *dev_spec = &hw->dev_spec.ich8lan; 16898cfa0ad2SJack F Vogel u32 act_offset; 16908cfa0ad2SJack F Vogel s32 ret_val = E1000_SUCCESS; 16918cfa0ad2SJack F Vogel u32 bank = 0; 16928cfa0ad2SJack F Vogel u16 i, word; 16938cfa0ad2SJack F Vogel 16948cfa0ad2SJack F Vogel DEBUGFUNC("e1000_read_nvm_ich8lan"); 16958cfa0ad2SJack F Vogel 16968cfa0ad2SJack F Vogel if ((offset >= nvm->word_size) || (words > nvm->word_size - offset) || 16978cfa0ad2SJack F Vogel (words == 0)) { 16988cfa0ad2SJack F Vogel DEBUGOUT("nvm parameter(s) out of bounds\n"); 16998cfa0ad2SJack F Vogel ret_val = -E1000_ERR_NVM; 17008cfa0ad2SJack F Vogel goto out; 17018cfa0ad2SJack F Vogel } 17028cfa0ad2SJack F Vogel 17034edd8523SJack F Vogel nvm->ops.acquire(hw); 17048cfa0ad2SJack F Vogel 17058cfa0ad2SJack F Vogel ret_val = e1000_valid_nvm_bank_detect_ich8lan(hw, &bank); 17064edd8523SJack F Vogel if (ret_val != E1000_SUCCESS) { 17074edd8523SJack F Vogel DEBUGOUT("Could not detect valid bank, assuming bank 0\n"); 17084edd8523SJack F Vogel bank = 0; 17094edd8523SJack F Vogel } 17108cfa0ad2SJack F Vogel 17118cfa0ad2SJack F Vogel act_offset = (bank) ? nvm->flash_bank_size : 0; 17128cfa0ad2SJack F Vogel act_offset += offset; 17138cfa0ad2SJack F Vogel 17144edd8523SJack F Vogel ret_val = E1000_SUCCESS; 17158cfa0ad2SJack F Vogel for (i = 0; i < words; i++) { 17168cfa0ad2SJack F Vogel if ((dev_spec->shadow_ram) && 17178cfa0ad2SJack F Vogel (dev_spec->shadow_ram[offset+i].modified)) { 17188cfa0ad2SJack F Vogel data[i] = dev_spec->shadow_ram[offset+i].value; 17198cfa0ad2SJack F Vogel } else { 17208cfa0ad2SJack F Vogel ret_val = e1000_read_flash_word_ich8lan(hw, 17218cfa0ad2SJack F Vogel act_offset + i, 17228cfa0ad2SJack F Vogel &word); 17238cfa0ad2SJack F Vogel if (ret_val) 17248cfa0ad2SJack F Vogel break; 17258cfa0ad2SJack F Vogel data[i] = word; 17268cfa0ad2SJack F Vogel } 17278cfa0ad2SJack F Vogel } 17288cfa0ad2SJack F Vogel 17298cfa0ad2SJack F Vogel nvm->ops.release(hw); 17308cfa0ad2SJack F Vogel 17318cfa0ad2SJack F Vogel out: 1732d035aa2dSJack F Vogel if (ret_val) 1733d035aa2dSJack F Vogel DEBUGOUT1("NVM read error: %d\n", ret_val); 1734d035aa2dSJack F Vogel 17358cfa0ad2SJack F Vogel return ret_val; 17368cfa0ad2SJack F Vogel } 17378cfa0ad2SJack F Vogel 17388cfa0ad2SJack F Vogel /** 17398cfa0ad2SJack F Vogel * e1000_flash_cycle_init_ich8lan - Initialize flash 17408cfa0ad2SJack F Vogel * @hw: pointer to the HW structure 17418cfa0ad2SJack F Vogel * 17428cfa0ad2SJack F Vogel * This function does initial flash setup so that a new read/write/erase cycle 17438cfa0ad2SJack F Vogel * can be started. 17448cfa0ad2SJack F Vogel **/ 17458cfa0ad2SJack F Vogel static s32 e1000_flash_cycle_init_ich8lan(struct e1000_hw *hw) 17468cfa0ad2SJack F Vogel { 17478cfa0ad2SJack F Vogel union ich8_hws_flash_status hsfsts; 17488cfa0ad2SJack F Vogel s32 ret_val = -E1000_ERR_NVM; 17498cfa0ad2SJack F Vogel s32 i = 0; 17508cfa0ad2SJack F Vogel 17518cfa0ad2SJack F Vogel DEBUGFUNC("e1000_flash_cycle_init_ich8lan"); 17528cfa0ad2SJack F Vogel 17538cfa0ad2SJack F Vogel hsfsts.regval = E1000_READ_FLASH_REG16(hw, ICH_FLASH_HSFSTS); 17548cfa0ad2SJack F Vogel 17558cfa0ad2SJack F Vogel /* Check if the flash descriptor is valid */ 17568cfa0ad2SJack F Vogel if (hsfsts.hsf_status.fldesvalid == 0) { 17578cfa0ad2SJack F Vogel DEBUGOUT("Flash descriptor invalid. " 17588cfa0ad2SJack F Vogel "SW Sequencing must be used."); 17598cfa0ad2SJack F Vogel goto out; 17608cfa0ad2SJack F Vogel } 17618cfa0ad2SJack F Vogel 17628cfa0ad2SJack F Vogel /* Clear FCERR and DAEL in hw status by writing 1 */ 17638cfa0ad2SJack F Vogel hsfsts.hsf_status.flcerr = 1; 17648cfa0ad2SJack F Vogel hsfsts.hsf_status.dael = 1; 17658cfa0ad2SJack F Vogel 17668cfa0ad2SJack F Vogel E1000_WRITE_FLASH_REG16(hw, ICH_FLASH_HSFSTS, hsfsts.regval); 17678cfa0ad2SJack F Vogel 17688cfa0ad2SJack F Vogel /* 17698cfa0ad2SJack F Vogel * Either we should have a hardware SPI cycle in progress 17708cfa0ad2SJack F Vogel * bit to check against, in order to start a new cycle or 17718cfa0ad2SJack F Vogel * FDONE bit should be changed in the hardware so that it 17728cfa0ad2SJack F Vogel * is 1 after hardware reset, which can then be used as an 17738cfa0ad2SJack F Vogel * indication whether a cycle is in progress or has been 17748cfa0ad2SJack F Vogel * completed. 17758cfa0ad2SJack F Vogel */ 17768cfa0ad2SJack F Vogel 17778cfa0ad2SJack F Vogel if (hsfsts.hsf_status.flcinprog == 0) { 17788cfa0ad2SJack F Vogel /* 17798cfa0ad2SJack F Vogel * There is no cycle running at present, 17808cfa0ad2SJack F Vogel * so we can start a cycle. 17818cfa0ad2SJack F Vogel * Begin by setting Flash Cycle Done. 17828cfa0ad2SJack F Vogel */ 17838cfa0ad2SJack F Vogel hsfsts.hsf_status.flcdone = 1; 17848cfa0ad2SJack F Vogel E1000_WRITE_FLASH_REG16(hw, ICH_FLASH_HSFSTS, hsfsts.regval); 17858cfa0ad2SJack F Vogel ret_val = E1000_SUCCESS; 17868cfa0ad2SJack F Vogel } else { 17878cfa0ad2SJack F Vogel /* 17888cfa0ad2SJack F Vogel * Otherwise poll for sometime so the current 17898cfa0ad2SJack F Vogel * cycle has a chance to end before giving up. 17908cfa0ad2SJack F Vogel */ 17918cfa0ad2SJack F Vogel for (i = 0; i < ICH_FLASH_READ_COMMAND_TIMEOUT; i++) { 17928cfa0ad2SJack F Vogel hsfsts.regval = E1000_READ_FLASH_REG16(hw, 17938cfa0ad2SJack F Vogel ICH_FLASH_HSFSTS); 17948cfa0ad2SJack F Vogel if (hsfsts.hsf_status.flcinprog == 0) { 17958cfa0ad2SJack F Vogel ret_val = E1000_SUCCESS; 17968cfa0ad2SJack F Vogel break; 17978cfa0ad2SJack F Vogel } 17988cfa0ad2SJack F Vogel usec_delay(1); 17998cfa0ad2SJack F Vogel } 18008cfa0ad2SJack F Vogel if (ret_val == E1000_SUCCESS) { 18018cfa0ad2SJack F Vogel /* 18028cfa0ad2SJack F Vogel * Successful in waiting for previous cycle to timeout, 18038cfa0ad2SJack F Vogel * now set the Flash Cycle Done. 18048cfa0ad2SJack F Vogel */ 18058cfa0ad2SJack F Vogel hsfsts.hsf_status.flcdone = 1; 1806daf9197cSJack F Vogel E1000_WRITE_FLASH_REG16(hw, ICH_FLASH_HSFSTS, 18078cfa0ad2SJack F Vogel hsfsts.regval); 18088cfa0ad2SJack F Vogel } else { 18098cfa0ad2SJack F Vogel DEBUGOUT("Flash controller busy, cannot get access"); 18108cfa0ad2SJack F Vogel } 18118cfa0ad2SJack F Vogel } 18128cfa0ad2SJack F Vogel 18138cfa0ad2SJack F Vogel out: 18148cfa0ad2SJack F Vogel return ret_val; 18158cfa0ad2SJack F Vogel } 18168cfa0ad2SJack F Vogel 18178cfa0ad2SJack F Vogel /** 18188cfa0ad2SJack F Vogel * e1000_flash_cycle_ich8lan - Starts flash cycle (read/write/erase) 18198cfa0ad2SJack F Vogel * @hw: pointer to the HW structure 18208cfa0ad2SJack F Vogel * @timeout: maximum time to wait for completion 18218cfa0ad2SJack F Vogel * 18228cfa0ad2SJack F Vogel * This function starts a flash cycle and waits for its completion. 18238cfa0ad2SJack F Vogel **/ 18248cfa0ad2SJack F Vogel static s32 e1000_flash_cycle_ich8lan(struct e1000_hw *hw, u32 timeout) 18258cfa0ad2SJack F Vogel { 18268cfa0ad2SJack F Vogel union ich8_hws_flash_ctrl hsflctl; 18278cfa0ad2SJack F Vogel union ich8_hws_flash_status hsfsts; 18288cfa0ad2SJack F Vogel s32 ret_val = -E1000_ERR_NVM; 18298cfa0ad2SJack F Vogel u32 i = 0; 18308cfa0ad2SJack F Vogel 18318cfa0ad2SJack F Vogel DEBUGFUNC("e1000_flash_cycle_ich8lan"); 18328cfa0ad2SJack F Vogel 18338cfa0ad2SJack F Vogel /* Start a cycle by writing 1 in Flash Cycle Go in Hw Flash Control */ 18348cfa0ad2SJack F Vogel hsflctl.regval = E1000_READ_FLASH_REG16(hw, ICH_FLASH_HSFCTL); 18358cfa0ad2SJack F Vogel hsflctl.hsf_ctrl.flcgo = 1; 18368cfa0ad2SJack F Vogel E1000_WRITE_FLASH_REG16(hw, ICH_FLASH_HSFCTL, hsflctl.regval); 18378cfa0ad2SJack F Vogel 18388cfa0ad2SJack F Vogel /* wait till FDONE bit is set to 1 */ 18398cfa0ad2SJack F Vogel do { 18408cfa0ad2SJack F Vogel hsfsts.regval = E1000_READ_FLASH_REG16(hw, ICH_FLASH_HSFSTS); 18418cfa0ad2SJack F Vogel if (hsfsts.hsf_status.flcdone == 1) 18428cfa0ad2SJack F Vogel break; 18438cfa0ad2SJack F Vogel usec_delay(1); 18448cfa0ad2SJack F Vogel } while (i++ < timeout); 18458cfa0ad2SJack F Vogel 18468cfa0ad2SJack F Vogel if (hsfsts.hsf_status.flcdone == 1 && hsfsts.hsf_status.flcerr == 0) 18478cfa0ad2SJack F Vogel ret_val = E1000_SUCCESS; 18488cfa0ad2SJack F Vogel 18498cfa0ad2SJack F Vogel return ret_val; 18508cfa0ad2SJack F Vogel } 18518cfa0ad2SJack F Vogel 18528cfa0ad2SJack F Vogel /** 18538cfa0ad2SJack F Vogel * e1000_read_flash_word_ich8lan - Read word from flash 18548cfa0ad2SJack F Vogel * @hw: pointer to the HW structure 18558cfa0ad2SJack F Vogel * @offset: offset to data location 18568cfa0ad2SJack F Vogel * @data: pointer to the location for storing the data 18578cfa0ad2SJack F Vogel * 18588cfa0ad2SJack F Vogel * Reads the flash word at offset into data. Offset is converted 18598cfa0ad2SJack F Vogel * to bytes before read. 18608cfa0ad2SJack F Vogel **/ 18618cfa0ad2SJack F Vogel static s32 e1000_read_flash_word_ich8lan(struct e1000_hw *hw, u32 offset, 18628cfa0ad2SJack F Vogel u16 *data) 18638cfa0ad2SJack F Vogel { 18648cfa0ad2SJack F Vogel s32 ret_val; 18658cfa0ad2SJack F Vogel 18668cfa0ad2SJack F Vogel DEBUGFUNC("e1000_read_flash_word_ich8lan"); 18678cfa0ad2SJack F Vogel 18688cfa0ad2SJack F Vogel if (!data) { 18698cfa0ad2SJack F Vogel ret_val = -E1000_ERR_NVM; 18708cfa0ad2SJack F Vogel goto out; 18718cfa0ad2SJack F Vogel } 18728cfa0ad2SJack F Vogel 18738cfa0ad2SJack F Vogel /* Must convert offset into bytes. */ 18748cfa0ad2SJack F Vogel offset <<= 1; 18758cfa0ad2SJack F Vogel 18768cfa0ad2SJack F Vogel ret_val = e1000_read_flash_data_ich8lan(hw, offset, 2, data); 18778cfa0ad2SJack F Vogel 18788cfa0ad2SJack F Vogel out: 18798cfa0ad2SJack F Vogel return ret_val; 18808cfa0ad2SJack F Vogel } 18818cfa0ad2SJack F Vogel 18828cfa0ad2SJack F Vogel /** 18838cfa0ad2SJack F Vogel * e1000_read_flash_byte_ich8lan - Read byte from flash 18848cfa0ad2SJack F Vogel * @hw: pointer to the HW structure 18858cfa0ad2SJack F Vogel * @offset: The offset of the byte to read. 18868cfa0ad2SJack F Vogel * @data: Pointer to a byte to store the value read. 18878cfa0ad2SJack F Vogel * 18888cfa0ad2SJack F Vogel * Reads a single byte from the NVM using the flash access registers. 18898cfa0ad2SJack F Vogel **/ 18908cfa0ad2SJack F Vogel static s32 e1000_read_flash_byte_ich8lan(struct e1000_hw *hw, u32 offset, 18918cfa0ad2SJack F Vogel u8 *data) 18928cfa0ad2SJack F Vogel { 18938cfa0ad2SJack F Vogel s32 ret_val = E1000_SUCCESS; 18948cfa0ad2SJack F Vogel u16 word = 0; 18958cfa0ad2SJack F Vogel 18968cfa0ad2SJack F Vogel ret_val = e1000_read_flash_data_ich8lan(hw, offset, 1, &word); 18978cfa0ad2SJack F Vogel if (ret_val) 18988cfa0ad2SJack F Vogel goto out; 18998cfa0ad2SJack F Vogel 19008cfa0ad2SJack F Vogel *data = (u8)word; 19018cfa0ad2SJack F Vogel 19028cfa0ad2SJack F Vogel out: 19038cfa0ad2SJack F Vogel return ret_val; 19048cfa0ad2SJack F Vogel } 19058cfa0ad2SJack F Vogel 19068cfa0ad2SJack F Vogel /** 19078cfa0ad2SJack F Vogel * e1000_read_flash_data_ich8lan - Read byte or word from NVM 19088cfa0ad2SJack F Vogel * @hw: pointer to the HW structure 19098cfa0ad2SJack F Vogel * @offset: The offset (in bytes) of the byte or word to read. 19108cfa0ad2SJack F Vogel * @size: Size of data to read, 1=byte 2=word 19118cfa0ad2SJack F Vogel * @data: Pointer to the word to store the value read. 19128cfa0ad2SJack F Vogel * 19138cfa0ad2SJack F Vogel * Reads a byte or word from the NVM using the flash access registers. 19148cfa0ad2SJack F Vogel **/ 19158cfa0ad2SJack F Vogel static s32 e1000_read_flash_data_ich8lan(struct e1000_hw *hw, u32 offset, 19168cfa0ad2SJack F Vogel u8 size, u16 *data) 19178cfa0ad2SJack F Vogel { 19188cfa0ad2SJack F Vogel union ich8_hws_flash_status hsfsts; 19198cfa0ad2SJack F Vogel union ich8_hws_flash_ctrl hsflctl; 19208cfa0ad2SJack F Vogel u32 flash_linear_addr; 19218cfa0ad2SJack F Vogel u32 flash_data = 0; 19228cfa0ad2SJack F Vogel s32 ret_val = -E1000_ERR_NVM; 19238cfa0ad2SJack F Vogel u8 count = 0; 19248cfa0ad2SJack F Vogel 19258cfa0ad2SJack F Vogel DEBUGFUNC("e1000_read_flash_data_ich8lan"); 19268cfa0ad2SJack F Vogel 19278cfa0ad2SJack F Vogel if (size < 1 || size > 2 || offset > ICH_FLASH_LINEAR_ADDR_MASK) 19288cfa0ad2SJack F Vogel goto out; 19298cfa0ad2SJack F Vogel 19308cfa0ad2SJack F Vogel flash_linear_addr = (ICH_FLASH_LINEAR_ADDR_MASK & offset) + 19318cfa0ad2SJack F Vogel hw->nvm.flash_base_addr; 19328cfa0ad2SJack F Vogel 19338cfa0ad2SJack F Vogel do { 19348cfa0ad2SJack F Vogel usec_delay(1); 19358cfa0ad2SJack F Vogel /* Steps */ 19368cfa0ad2SJack F Vogel ret_val = e1000_flash_cycle_init_ich8lan(hw); 19378cfa0ad2SJack F Vogel if (ret_val != E1000_SUCCESS) 19388cfa0ad2SJack F Vogel break; 19398cfa0ad2SJack F Vogel 19408cfa0ad2SJack F Vogel hsflctl.regval = E1000_READ_FLASH_REG16(hw, ICH_FLASH_HSFCTL); 19418cfa0ad2SJack F Vogel /* 0b/1b corresponds to 1 or 2 byte size, respectively. */ 19428cfa0ad2SJack F Vogel hsflctl.hsf_ctrl.fldbcount = size - 1; 19438cfa0ad2SJack F Vogel hsflctl.hsf_ctrl.flcycle = ICH_CYCLE_READ; 19448cfa0ad2SJack F Vogel E1000_WRITE_FLASH_REG16(hw, ICH_FLASH_HSFCTL, hsflctl.regval); 19458cfa0ad2SJack F Vogel 19468cfa0ad2SJack F Vogel E1000_WRITE_FLASH_REG(hw, ICH_FLASH_FADDR, flash_linear_addr); 19478cfa0ad2SJack F Vogel 19488cfa0ad2SJack F Vogel ret_val = e1000_flash_cycle_ich8lan(hw, 19498cfa0ad2SJack F Vogel ICH_FLASH_READ_COMMAND_TIMEOUT); 19508cfa0ad2SJack F Vogel 19518cfa0ad2SJack F Vogel /* 19528cfa0ad2SJack F Vogel * Check if FCERR is set to 1, if set to 1, clear it 19538cfa0ad2SJack F Vogel * and try the whole sequence a few more times, else 19548cfa0ad2SJack F Vogel * read in (shift in) the Flash Data0, the order is 19558cfa0ad2SJack F Vogel * least significant byte first msb to lsb 19568cfa0ad2SJack F Vogel */ 19578cfa0ad2SJack F Vogel if (ret_val == E1000_SUCCESS) { 19588cfa0ad2SJack F Vogel flash_data = E1000_READ_FLASH_REG(hw, ICH_FLASH_FDATA0); 1959daf9197cSJack F Vogel if (size == 1) 19608cfa0ad2SJack F Vogel *data = (u8)(flash_data & 0x000000FF); 1961daf9197cSJack F Vogel else if (size == 2) 19628cfa0ad2SJack F Vogel *data = (u16)(flash_data & 0x0000FFFF); 19638cfa0ad2SJack F Vogel break; 19648cfa0ad2SJack F Vogel } else { 19658cfa0ad2SJack F Vogel /* 19668cfa0ad2SJack F Vogel * If we've gotten here, then things are probably 19678cfa0ad2SJack F Vogel * completely hosed, but if the error condition is 19688cfa0ad2SJack F Vogel * detected, it won't hurt to give it another try... 19698cfa0ad2SJack F Vogel * ICH_FLASH_CYCLE_REPEAT_COUNT times. 19708cfa0ad2SJack F Vogel */ 19718cfa0ad2SJack F Vogel hsfsts.regval = E1000_READ_FLASH_REG16(hw, 19728cfa0ad2SJack F Vogel ICH_FLASH_HSFSTS); 19738cfa0ad2SJack F Vogel if (hsfsts.hsf_status.flcerr == 1) { 19748cfa0ad2SJack F Vogel /* Repeat for some time before giving up. */ 19758cfa0ad2SJack F Vogel continue; 19768cfa0ad2SJack F Vogel } else if (hsfsts.hsf_status.flcdone == 0) { 19778cfa0ad2SJack F Vogel DEBUGOUT("Timeout error - flash cycle " 19788cfa0ad2SJack F Vogel "did not complete."); 19798cfa0ad2SJack F Vogel break; 19808cfa0ad2SJack F Vogel } 19818cfa0ad2SJack F Vogel } 19828cfa0ad2SJack F Vogel } while (count++ < ICH_FLASH_CYCLE_REPEAT_COUNT); 19838cfa0ad2SJack F Vogel 19848cfa0ad2SJack F Vogel out: 19858cfa0ad2SJack F Vogel return ret_val; 19868cfa0ad2SJack F Vogel } 19878cfa0ad2SJack F Vogel 19888cfa0ad2SJack F Vogel /** 19898cfa0ad2SJack F Vogel * e1000_write_nvm_ich8lan - Write word(s) to the NVM 19908cfa0ad2SJack F Vogel * @hw: pointer to the HW structure 19918cfa0ad2SJack F Vogel * @offset: The offset (in bytes) of the word(s) to write. 19928cfa0ad2SJack F Vogel * @words: Size of data to write in words 19938cfa0ad2SJack F Vogel * @data: Pointer to the word(s) to write at offset. 19948cfa0ad2SJack F Vogel * 19958cfa0ad2SJack F Vogel * Writes a byte or word to the NVM using the flash access registers. 19968cfa0ad2SJack F Vogel **/ 19978cfa0ad2SJack F Vogel static s32 e1000_write_nvm_ich8lan(struct e1000_hw *hw, u16 offset, u16 words, 19988cfa0ad2SJack F Vogel u16 *data) 19998cfa0ad2SJack F Vogel { 20008cfa0ad2SJack F Vogel struct e1000_nvm_info *nvm = &hw->nvm; 2001daf9197cSJack F Vogel struct e1000_dev_spec_ich8lan *dev_spec = &hw->dev_spec.ich8lan; 20028cfa0ad2SJack F Vogel s32 ret_val = E1000_SUCCESS; 20038cfa0ad2SJack F Vogel u16 i; 20048cfa0ad2SJack F Vogel 20058cfa0ad2SJack F Vogel DEBUGFUNC("e1000_write_nvm_ich8lan"); 20068cfa0ad2SJack F Vogel 20078cfa0ad2SJack F Vogel if ((offset >= nvm->word_size) || (words > nvm->word_size - offset) || 20088cfa0ad2SJack F Vogel (words == 0)) { 20098cfa0ad2SJack F Vogel DEBUGOUT("nvm parameter(s) out of bounds\n"); 20108cfa0ad2SJack F Vogel ret_val = -E1000_ERR_NVM; 20118cfa0ad2SJack F Vogel goto out; 20128cfa0ad2SJack F Vogel } 20138cfa0ad2SJack F Vogel 20144edd8523SJack F Vogel nvm->ops.acquire(hw); 20158cfa0ad2SJack F Vogel 20168cfa0ad2SJack F Vogel for (i = 0; i < words; i++) { 20178cfa0ad2SJack F Vogel dev_spec->shadow_ram[offset+i].modified = TRUE; 20188cfa0ad2SJack F Vogel dev_spec->shadow_ram[offset+i].value = data[i]; 20198cfa0ad2SJack F Vogel } 20208cfa0ad2SJack F Vogel 20218cfa0ad2SJack F Vogel nvm->ops.release(hw); 20228cfa0ad2SJack F Vogel 20238cfa0ad2SJack F Vogel out: 20248cfa0ad2SJack F Vogel return ret_val; 20258cfa0ad2SJack F Vogel } 20268cfa0ad2SJack F Vogel 20278cfa0ad2SJack F Vogel /** 20288cfa0ad2SJack F Vogel * e1000_update_nvm_checksum_ich8lan - Update the checksum for NVM 20298cfa0ad2SJack F Vogel * @hw: pointer to the HW structure 20308cfa0ad2SJack F Vogel * 20318cfa0ad2SJack F Vogel * The NVM checksum is updated by calling the generic update_nvm_checksum, 20328cfa0ad2SJack F Vogel * which writes the checksum to the shadow ram. The changes in the shadow 20338cfa0ad2SJack F Vogel * ram are then committed to the EEPROM by processing each bank at a time 20348cfa0ad2SJack F Vogel * checking for the modified bit and writing only the pending changes. 20358cfa0ad2SJack F Vogel * After a successful commit, the shadow ram is cleared and is ready for 20368cfa0ad2SJack F Vogel * future writes. 20378cfa0ad2SJack F Vogel **/ 20388cfa0ad2SJack F Vogel static s32 e1000_update_nvm_checksum_ich8lan(struct e1000_hw *hw) 20398cfa0ad2SJack F Vogel { 20408cfa0ad2SJack F Vogel struct e1000_nvm_info *nvm = &hw->nvm; 2041daf9197cSJack F Vogel struct e1000_dev_spec_ich8lan *dev_spec = &hw->dev_spec.ich8lan; 20428cfa0ad2SJack F Vogel u32 i, act_offset, new_bank_offset, old_bank_offset, bank; 20438cfa0ad2SJack F Vogel s32 ret_val; 20448cfa0ad2SJack F Vogel u16 data; 20458cfa0ad2SJack F Vogel 20468cfa0ad2SJack F Vogel DEBUGFUNC("e1000_update_nvm_checksum_ich8lan"); 20478cfa0ad2SJack F Vogel 20488cfa0ad2SJack F Vogel ret_val = e1000_update_nvm_checksum_generic(hw); 20498cfa0ad2SJack F Vogel if (ret_val) 20508cfa0ad2SJack F Vogel goto out; 20518cfa0ad2SJack F Vogel 20528cfa0ad2SJack F Vogel if (nvm->type != e1000_nvm_flash_sw) 20538cfa0ad2SJack F Vogel goto out; 20548cfa0ad2SJack F Vogel 20554edd8523SJack F Vogel nvm->ops.acquire(hw); 20568cfa0ad2SJack F Vogel 20578cfa0ad2SJack F Vogel /* 20588cfa0ad2SJack F Vogel * We're writing to the opposite bank so if we're on bank 1, 20598cfa0ad2SJack F Vogel * write to bank 0 etc. We also need to erase the segment that 20608cfa0ad2SJack F Vogel * is going to be written 20618cfa0ad2SJack F Vogel */ 20628cfa0ad2SJack F Vogel ret_val = e1000_valid_nvm_bank_detect_ich8lan(hw, &bank); 2063d035aa2dSJack F Vogel if (ret_val != E1000_SUCCESS) { 20644edd8523SJack F Vogel DEBUGOUT("Could not detect valid bank, assuming bank 0\n"); 20654edd8523SJack F Vogel bank = 0; 2066d035aa2dSJack F Vogel } 20678cfa0ad2SJack F Vogel 20688cfa0ad2SJack F Vogel if (bank == 0) { 20698cfa0ad2SJack F Vogel new_bank_offset = nvm->flash_bank_size; 20708cfa0ad2SJack F Vogel old_bank_offset = 0; 2071d035aa2dSJack F Vogel ret_val = e1000_erase_flash_bank_ich8lan(hw, 1); 2072a69ed8dfSJack F Vogel if (ret_val) 2073a69ed8dfSJack F Vogel goto release; 20748cfa0ad2SJack F Vogel } else { 20758cfa0ad2SJack F Vogel old_bank_offset = nvm->flash_bank_size; 20768cfa0ad2SJack F Vogel new_bank_offset = 0; 2077d035aa2dSJack F Vogel ret_val = e1000_erase_flash_bank_ich8lan(hw, 0); 2078a69ed8dfSJack F Vogel if (ret_val) 2079a69ed8dfSJack F Vogel goto release; 20808cfa0ad2SJack F Vogel } 20818cfa0ad2SJack F Vogel 20828cfa0ad2SJack F Vogel for (i = 0; i < E1000_SHADOW_RAM_WORDS; i++) { 20838cfa0ad2SJack F Vogel /* 20848cfa0ad2SJack F Vogel * Determine whether to write the value stored 20858cfa0ad2SJack F Vogel * in the other NVM bank or a modified value stored 20868cfa0ad2SJack F Vogel * in the shadow RAM 20878cfa0ad2SJack F Vogel */ 20888cfa0ad2SJack F Vogel if (dev_spec->shadow_ram[i].modified) { 20898cfa0ad2SJack F Vogel data = dev_spec->shadow_ram[i].value; 20908cfa0ad2SJack F Vogel } else { 2091d035aa2dSJack F Vogel ret_val = e1000_read_flash_word_ich8lan(hw, i + 2092d035aa2dSJack F Vogel old_bank_offset, 20938cfa0ad2SJack F Vogel &data); 2094d035aa2dSJack F Vogel if (ret_val) 2095d035aa2dSJack F Vogel break; 20968cfa0ad2SJack F Vogel } 20978cfa0ad2SJack F Vogel 20988cfa0ad2SJack F Vogel /* 20998cfa0ad2SJack F Vogel * If the word is 0x13, then make sure the signature bits 21008cfa0ad2SJack F Vogel * (15:14) are 11b until the commit has completed. 21018cfa0ad2SJack F Vogel * This will allow us to write 10b which indicates the 21028cfa0ad2SJack F Vogel * signature is valid. We want to do this after the write 21038cfa0ad2SJack F Vogel * has completed so that we don't mark the segment valid 21048cfa0ad2SJack F Vogel * while the write is still in progress 21058cfa0ad2SJack F Vogel */ 21068cfa0ad2SJack F Vogel if (i == E1000_ICH_NVM_SIG_WORD) 21078cfa0ad2SJack F Vogel data |= E1000_ICH_NVM_SIG_MASK; 21088cfa0ad2SJack F Vogel 21098cfa0ad2SJack F Vogel /* Convert offset to bytes. */ 21108cfa0ad2SJack F Vogel act_offset = (i + new_bank_offset) << 1; 21118cfa0ad2SJack F Vogel 21128cfa0ad2SJack F Vogel usec_delay(100); 21138cfa0ad2SJack F Vogel /* Write the bytes to the new bank. */ 21148cfa0ad2SJack F Vogel ret_val = e1000_retry_write_flash_byte_ich8lan(hw, 21158cfa0ad2SJack F Vogel act_offset, 21168cfa0ad2SJack F Vogel (u8)data); 21178cfa0ad2SJack F Vogel if (ret_val) 21188cfa0ad2SJack F Vogel break; 21198cfa0ad2SJack F Vogel 21208cfa0ad2SJack F Vogel usec_delay(100); 21218cfa0ad2SJack F Vogel ret_val = e1000_retry_write_flash_byte_ich8lan(hw, 21228cfa0ad2SJack F Vogel act_offset + 1, 21238cfa0ad2SJack F Vogel (u8)(data >> 8)); 21248cfa0ad2SJack F Vogel if (ret_val) 21258cfa0ad2SJack F Vogel break; 21268cfa0ad2SJack F Vogel } 21278cfa0ad2SJack F Vogel 21288cfa0ad2SJack F Vogel /* 21298cfa0ad2SJack F Vogel * Don't bother writing the segment valid bits if sector 21308cfa0ad2SJack F Vogel * programming failed. 21318cfa0ad2SJack F Vogel */ 21328cfa0ad2SJack F Vogel if (ret_val) { 21338cfa0ad2SJack F Vogel DEBUGOUT("Flash commit failed.\n"); 2134a69ed8dfSJack F Vogel goto release; 21358cfa0ad2SJack F Vogel } 21368cfa0ad2SJack F Vogel 21378cfa0ad2SJack F Vogel /* 21388cfa0ad2SJack F Vogel * Finally validate the new segment by setting bit 15:14 21398cfa0ad2SJack F Vogel * to 10b in word 0x13 , this can be done without an 21408cfa0ad2SJack F Vogel * erase as well since these bits are 11 to start with 21418cfa0ad2SJack F Vogel * and we need to change bit 14 to 0b 21428cfa0ad2SJack F Vogel */ 21438cfa0ad2SJack F Vogel act_offset = new_bank_offset + E1000_ICH_NVM_SIG_WORD; 2144d035aa2dSJack F Vogel ret_val = e1000_read_flash_word_ich8lan(hw, act_offset, &data); 2145a69ed8dfSJack F Vogel if (ret_val) 2146a69ed8dfSJack F Vogel goto release; 21474edd8523SJack F Vogel 21488cfa0ad2SJack F Vogel data &= 0xBFFF; 21498cfa0ad2SJack F Vogel ret_val = e1000_retry_write_flash_byte_ich8lan(hw, 21508cfa0ad2SJack F Vogel act_offset * 2 + 1, 21518cfa0ad2SJack F Vogel (u8)(data >> 8)); 2152a69ed8dfSJack F Vogel if (ret_val) 2153a69ed8dfSJack F Vogel goto release; 21548cfa0ad2SJack F Vogel 21558cfa0ad2SJack F Vogel /* 21568cfa0ad2SJack F Vogel * And invalidate the previously valid segment by setting 21578cfa0ad2SJack F Vogel * its signature word (0x13) high_byte to 0b. This can be 21588cfa0ad2SJack F Vogel * done without an erase because flash erase sets all bits 21598cfa0ad2SJack F Vogel * to 1's. We can write 1's to 0's without an erase 21608cfa0ad2SJack F Vogel */ 21618cfa0ad2SJack F Vogel act_offset = (old_bank_offset + E1000_ICH_NVM_SIG_WORD) * 2 + 1; 21628cfa0ad2SJack F Vogel ret_val = e1000_retry_write_flash_byte_ich8lan(hw, act_offset, 0); 2163a69ed8dfSJack F Vogel if (ret_val) 2164a69ed8dfSJack F Vogel goto release; 21658cfa0ad2SJack F Vogel 21668cfa0ad2SJack F Vogel /* Great! Everything worked, we can now clear the cached entries. */ 21678cfa0ad2SJack F Vogel for (i = 0; i < E1000_SHADOW_RAM_WORDS; i++) { 21688cfa0ad2SJack F Vogel dev_spec->shadow_ram[i].modified = FALSE; 21698cfa0ad2SJack F Vogel dev_spec->shadow_ram[i].value = 0xFFFF; 21708cfa0ad2SJack F Vogel } 21718cfa0ad2SJack F Vogel 2172a69ed8dfSJack F Vogel release: 21738cfa0ad2SJack F Vogel nvm->ops.release(hw); 21748cfa0ad2SJack F Vogel 21758cfa0ad2SJack F Vogel /* 21768cfa0ad2SJack F Vogel * Reload the EEPROM, or else modifications will not appear 21778cfa0ad2SJack F Vogel * until after the next adapter reset. 21788cfa0ad2SJack F Vogel */ 2179a69ed8dfSJack F Vogel if (!ret_val) { 21808cfa0ad2SJack F Vogel nvm->ops.reload(hw); 21818cfa0ad2SJack F Vogel msec_delay(10); 2182a69ed8dfSJack F Vogel } 21838cfa0ad2SJack F Vogel 21848cfa0ad2SJack F Vogel out: 2185d035aa2dSJack F Vogel if (ret_val) 2186d035aa2dSJack F Vogel DEBUGOUT1("NVM update error: %d\n", ret_val); 2187d035aa2dSJack F Vogel 21888cfa0ad2SJack F Vogel return ret_val; 21898cfa0ad2SJack F Vogel } 21908cfa0ad2SJack F Vogel 21918cfa0ad2SJack F Vogel /** 21928cfa0ad2SJack F Vogel * e1000_validate_nvm_checksum_ich8lan - Validate EEPROM checksum 21938cfa0ad2SJack F Vogel * @hw: pointer to the HW structure 21948cfa0ad2SJack F Vogel * 21958cfa0ad2SJack F Vogel * Check to see if checksum needs to be fixed by reading bit 6 in word 0x19. 2196daf9197cSJack F Vogel * If the bit is 0, that the EEPROM had been modified, but the checksum was not 2197daf9197cSJack F Vogel * calculated, in which case we need to calculate the checksum and set bit 6. 21988cfa0ad2SJack F Vogel **/ 21998cfa0ad2SJack F Vogel static s32 e1000_validate_nvm_checksum_ich8lan(struct e1000_hw *hw) 22008cfa0ad2SJack F Vogel { 22018cfa0ad2SJack F Vogel s32 ret_val = E1000_SUCCESS; 22028cfa0ad2SJack F Vogel u16 data; 22038cfa0ad2SJack F Vogel 22048cfa0ad2SJack F Vogel DEBUGFUNC("e1000_validate_nvm_checksum_ich8lan"); 22058cfa0ad2SJack F Vogel 22068cfa0ad2SJack F Vogel /* 22078cfa0ad2SJack F Vogel * Read 0x19 and check bit 6. If this bit is 0, the checksum 22088cfa0ad2SJack F Vogel * needs to be fixed. This bit is an indication that the NVM 22098cfa0ad2SJack F Vogel * was prepared by OEM software and did not calculate the 22108cfa0ad2SJack F Vogel * checksum...a likely scenario. 22118cfa0ad2SJack F Vogel */ 22128cfa0ad2SJack F Vogel ret_val = hw->nvm.ops.read(hw, 0x19, 1, &data); 22138cfa0ad2SJack F Vogel if (ret_val) 22148cfa0ad2SJack F Vogel goto out; 22158cfa0ad2SJack F Vogel 22168cfa0ad2SJack F Vogel if ((data & 0x40) == 0) { 22178cfa0ad2SJack F Vogel data |= 0x40; 22188cfa0ad2SJack F Vogel ret_val = hw->nvm.ops.write(hw, 0x19, 1, &data); 22198cfa0ad2SJack F Vogel if (ret_val) 22208cfa0ad2SJack F Vogel goto out; 22218cfa0ad2SJack F Vogel ret_val = hw->nvm.ops.update(hw); 22228cfa0ad2SJack F Vogel if (ret_val) 22238cfa0ad2SJack F Vogel goto out; 22248cfa0ad2SJack F Vogel } 22258cfa0ad2SJack F Vogel 22268cfa0ad2SJack F Vogel ret_val = e1000_validate_nvm_checksum_generic(hw); 22278cfa0ad2SJack F Vogel 22288cfa0ad2SJack F Vogel out: 22298cfa0ad2SJack F Vogel return ret_val; 22308cfa0ad2SJack F Vogel } 22318cfa0ad2SJack F Vogel 22328cfa0ad2SJack F Vogel /** 22338cfa0ad2SJack F Vogel * e1000_write_flash_data_ich8lan - Writes bytes to the NVM 22348cfa0ad2SJack F Vogel * @hw: pointer to the HW structure 22358cfa0ad2SJack F Vogel * @offset: The offset (in bytes) of the byte/word to read. 22368cfa0ad2SJack F Vogel * @size: Size of data to read, 1=byte 2=word 22378cfa0ad2SJack F Vogel * @data: The byte(s) to write to the NVM. 22388cfa0ad2SJack F Vogel * 22398cfa0ad2SJack F Vogel * Writes one/two bytes to the NVM using the flash access registers. 22408cfa0ad2SJack F Vogel **/ 22418cfa0ad2SJack F Vogel static s32 e1000_write_flash_data_ich8lan(struct e1000_hw *hw, u32 offset, 22428cfa0ad2SJack F Vogel u8 size, u16 data) 22438cfa0ad2SJack F Vogel { 22448cfa0ad2SJack F Vogel union ich8_hws_flash_status hsfsts; 22458cfa0ad2SJack F Vogel union ich8_hws_flash_ctrl hsflctl; 22468cfa0ad2SJack F Vogel u32 flash_linear_addr; 22478cfa0ad2SJack F Vogel u32 flash_data = 0; 22488cfa0ad2SJack F Vogel s32 ret_val = -E1000_ERR_NVM; 22498cfa0ad2SJack F Vogel u8 count = 0; 22508cfa0ad2SJack F Vogel 22518cfa0ad2SJack F Vogel DEBUGFUNC("e1000_write_ich8_data"); 22528cfa0ad2SJack F Vogel 22538cfa0ad2SJack F Vogel if (size < 1 || size > 2 || data > size * 0xff || 22548cfa0ad2SJack F Vogel offset > ICH_FLASH_LINEAR_ADDR_MASK) 22558cfa0ad2SJack F Vogel goto out; 22568cfa0ad2SJack F Vogel 22578cfa0ad2SJack F Vogel flash_linear_addr = (ICH_FLASH_LINEAR_ADDR_MASK & offset) + 22588cfa0ad2SJack F Vogel hw->nvm.flash_base_addr; 22598cfa0ad2SJack F Vogel 22608cfa0ad2SJack F Vogel do { 22618cfa0ad2SJack F Vogel usec_delay(1); 22628cfa0ad2SJack F Vogel /* Steps */ 22638cfa0ad2SJack F Vogel ret_val = e1000_flash_cycle_init_ich8lan(hw); 22648cfa0ad2SJack F Vogel if (ret_val != E1000_SUCCESS) 22658cfa0ad2SJack F Vogel break; 22668cfa0ad2SJack F Vogel 22678cfa0ad2SJack F Vogel hsflctl.regval = E1000_READ_FLASH_REG16(hw, ICH_FLASH_HSFCTL); 22688cfa0ad2SJack F Vogel /* 0b/1b corresponds to 1 or 2 byte size, respectively. */ 22698cfa0ad2SJack F Vogel hsflctl.hsf_ctrl.fldbcount = size - 1; 22708cfa0ad2SJack F Vogel hsflctl.hsf_ctrl.flcycle = ICH_CYCLE_WRITE; 22718cfa0ad2SJack F Vogel E1000_WRITE_FLASH_REG16(hw, ICH_FLASH_HSFCTL, hsflctl.regval); 22728cfa0ad2SJack F Vogel 22738cfa0ad2SJack F Vogel E1000_WRITE_FLASH_REG(hw, ICH_FLASH_FADDR, flash_linear_addr); 22748cfa0ad2SJack F Vogel 22758cfa0ad2SJack F Vogel if (size == 1) 22768cfa0ad2SJack F Vogel flash_data = (u32)data & 0x00FF; 22778cfa0ad2SJack F Vogel else 22788cfa0ad2SJack F Vogel flash_data = (u32)data; 22798cfa0ad2SJack F Vogel 22808cfa0ad2SJack F Vogel E1000_WRITE_FLASH_REG(hw, ICH_FLASH_FDATA0, flash_data); 22818cfa0ad2SJack F Vogel 22828cfa0ad2SJack F Vogel /* 22838cfa0ad2SJack F Vogel * check if FCERR is set to 1 , if set to 1, clear it 22848cfa0ad2SJack F Vogel * and try the whole sequence a few more times else done 22858cfa0ad2SJack F Vogel */ 22868cfa0ad2SJack F Vogel ret_val = e1000_flash_cycle_ich8lan(hw, 22878cfa0ad2SJack F Vogel ICH_FLASH_WRITE_COMMAND_TIMEOUT); 2288daf9197cSJack F Vogel if (ret_val == E1000_SUCCESS) 22898cfa0ad2SJack F Vogel break; 2290daf9197cSJack F Vogel 22918cfa0ad2SJack F Vogel /* 22928cfa0ad2SJack F Vogel * If we're here, then things are most likely 22938cfa0ad2SJack F Vogel * completely hosed, but if the error condition 22948cfa0ad2SJack F Vogel * is detected, it won't hurt to give it another 22958cfa0ad2SJack F Vogel * try...ICH_FLASH_CYCLE_REPEAT_COUNT times. 22968cfa0ad2SJack F Vogel */ 2297daf9197cSJack F Vogel hsfsts.regval = E1000_READ_FLASH_REG16(hw, ICH_FLASH_HSFSTS); 22984edd8523SJack F Vogel if (hsfsts.hsf_status.flcerr == 1) 22998cfa0ad2SJack F Vogel /* Repeat for some time before giving up. */ 23008cfa0ad2SJack F Vogel continue; 23014edd8523SJack F Vogel if (hsfsts.hsf_status.flcdone == 0) { 23028cfa0ad2SJack F Vogel DEBUGOUT("Timeout error - flash cycle " 23038cfa0ad2SJack F Vogel "did not complete."); 23048cfa0ad2SJack F Vogel break; 23058cfa0ad2SJack F Vogel } 23068cfa0ad2SJack F Vogel } while (count++ < ICH_FLASH_CYCLE_REPEAT_COUNT); 23078cfa0ad2SJack F Vogel 23088cfa0ad2SJack F Vogel out: 23098cfa0ad2SJack F Vogel return ret_val; 23108cfa0ad2SJack F Vogel } 23118cfa0ad2SJack F Vogel 23128cfa0ad2SJack F Vogel /** 23138cfa0ad2SJack F Vogel * e1000_write_flash_byte_ich8lan - Write a single byte to NVM 23148cfa0ad2SJack F Vogel * @hw: pointer to the HW structure 23158cfa0ad2SJack F Vogel * @offset: The index of the byte to read. 23168cfa0ad2SJack F Vogel * @data: The byte to write to the NVM. 23178cfa0ad2SJack F Vogel * 23188cfa0ad2SJack F Vogel * Writes a single byte to the NVM using the flash access registers. 23198cfa0ad2SJack F Vogel **/ 23208cfa0ad2SJack F Vogel static s32 e1000_write_flash_byte_ich8lan(struct e1000_hw *hw, u32 offset, 23218cfa0ad2SJack F Vogel u8 data) 23228cfa0ad2SJack F Vogel { 23238cfa0ad2SJack F Vogel u16 word = (u16)data; 23248cfa0ad2SJack F Vogel 23258cfa0ad2SJack F Vogel DEBUGFUNC("e1000_write_flash_byte_ich8lan"); 23268cfa0ad2SJack F Vogel 23278cfa0ad2SJack F Vogel return e1000_write_flash_data_ich8lan(hw, offset, 1, word); 23288cfa0ad2SJack F Vogel } 23298cfa0ad2SJack F Vogel 23308cfa0ad2SJack F Vogel /** 23318cfa0ad2SJack F Vogel * e1000_retry_write_flash_byte_ich8lan - Writes a single byte to NVM 23328cfa0ad2SJack F Vogel * @hw: pointer to the HW structure 23338cfa0ad2SJack F Vogel * @offset: The offset of the byte to write. 23348cfa0ad2SJack F Vogel * @byte: The byte to write to the NVM. 23358cfa0ad2SJack F Vogel * 23368cfa0ad2SJack F Vogel * Writes a single byte to the NVM using the flash access registers. 23378cfa0ad2SJack F Vogel * Goes through a retry algorithm before giving up. 23388cfa0ad2SJack F Vogel **/ 23398cfa0ad2SJack F Vogel static s32 e1000_retry_write_flash_byte_ich8lan(struct e1000_hw *hw, 23408cfa0ad2SJack F Vogel u32 offset, u8 byte) 23418cfa0ad2SJack F Vogel { 23428cfa0ad2SJack F Vogel s32 ret_val; 23438cfa0ad2SJack F Vogel u16 program_retries; 23448cfa0ad2SJack F Vogel 23458cfa0ad2SJack F Vogel DEBUGFUNC("e1000_retry_write_flash_byte_ich8lan"); 23468cfa0ad2SJack F Vogel 23478cfa0ad2SJack F Vogel ret_val = e1000_write_flash_byte_ich8lan(hw, offset, byte); 23488cfa0ad2SJack F Vogel if (ret_val == E1000_SUCCESS) 23498cfa0ad2SJack F Vogel goto out; 23508cfa0ad2SJack F Vogel 23518cfa0ad2SJack F Vogel for (program_retries = 0; program_retries < 100; program_retries++) { 23528cfa0ad2SJack F Vogel DEBUGOUT2("Retrying Byte %2.2X at offset %u\n", byte, offset); 23538cfa0ad2SJack F Vogel usec_delay(100); 23548cfa0ad2SJack F Vogel ret_val = e1000_write_flash_byte_ich8lan(hw, offset, byte); 23558cfa0ad2SJack F Vogel if (ret_val == E1000_SUCCESS) 23568cfa0ad2SJack F Vogel break; 23578cfa0ad2SJack F Vogel } 23588cfa0ad2SJack F Vogel if (program_retries == 100) { 23598cfa0ad2SJack F Vogel ret_val = -E1000_ERR_NVM; 23608cfa0ad2SJack F Vogel goto out; 23618cfa0ad2SJack F Vogel } 23628cfa0ad2SJack F Vogel 23638cfa0ad2SJack F Vogel out: 23648cfa0ad2SJack F Vogel return ret_val; 23658cfa0ad2SJack F Vogel } 23668cfa0ad2SJack F Vogel 23678cfa0ad2SJack F Vogel /** 23688cfa0ad2SJack F Vogel * e1000_erase_flash_bank_ich8lan - Erase a bank (4k) from NVM 23698cfa0ad2SJack F Vogel * @hw: pointer to the HW structure 23708cfa0ad2SJack F Vogel * @bank: 0 for first bank, 1 for second bank, etc. 23718cfa0ad2SJack F Vogel * 23728cfa0ad2SJack F Vogel * Erases the bank specified. Each bank is a 4k block. Banks are 0 based. 23738cfa0ad2SJack F Vogel * bank N is 4096 * N + flash_reg_addr. 23748cfa0ad2SJack F Vogel **/ 23758cfa0ad2SJack F Vogel static s32 e1000_erase_flash_bank_ich8lan(struct e1000_hw *hw, u32 bank) 23768cfa0ad2SJack F Vogel { 23778cfa0ad2SJack F Vogel struct e1000_nvm_info *nvm = &hw->nvm; 23788cfa0ad2SJack F Vogel union ich8_hws_flash_status hsfsts; 23798cfa0ad2SJack F Vogel union ich8_hws_flash_ctrl hsflctl; 23808cfa0ad2SJack F Vogel u32 flash_linear_addr; 23818cfa0ad2SJack F Vogel /* bank size is in 16bit words - adjust to bytes */ 23828cfa0ad2SJack F Vogel u32 flash_bank_size = nvm->flash_bank_size * 2; 23838cfa0ad2SJack F Vogel s32 ret_val = E1000_SUCCESS; 23848cfa0ad2SJack F Vogel s32 count = 0; 23858cfa0ad2SJack F Vogel s32 j, iteration, sector_size; 23868cfa0ad2SJack F Vogel 23878cfa0ad2SJack F Vogel DEBUGFUNC("e1000_erase_flash_bank_ich8lan"); 23888cfa0ad2SJack F Vogel 23898cfa0ad2SJack F Vogel hsfsts.regval = E1000_READ_FLASH_REG16(hw, ICH_FLASH_HSFSTS); 23908cfa0ad2SJack F Vogel 23918cfa0ad2SJack F Vogel /* 23928cfa0ad2SJack F Vogel * Determine HW Sector size: Read BERASE bits of hw flash status 23938cfa0ad2SJack F Vogel * register 23948cfa0ad2SJack F Vogel * 00: The Hw sector is 256 bytes, hence we need to erase 16 23958cfa0ad2SJack F Vogel * consecutive sectors. The start index for the nth Hw sector 23968cfa0ad2SJack F Vogel * can be calculated as = bank * 4096 + n * 256 23978cfa0ad2SJack F Vogel * 01: The Hw sector is 4K bytes, hence we need to erase 1 sector. 23988cfa0ad2SJack F Vogel * The start index for the nth Hw sector can be calculated 23998cfa0ad2SJack F Vogel * as = bank * 4096 24008cfa0ad2SJack F Vogel * 10: The Hw sector is 8K bytes, nth sector = bank * 8192 24018cfa0ad2SJack F Vogel * (ich9 only, otherwise error condition) 24028cfa0ad2SJack F Vogel * 11: The Hw sector is 64K bytes, nth sector = bank * 65536 24038cfa0ad2SJack F Vogel */ 24048cfa0ad2SJack F Vogel switch (hsfsts.hsf_status.berasesz) { 24058cfa0ad2SJack F Vogel case 0: 24068cfa0ad2SJack F Vogel /* Hw sector size 256 */ 24078cfa0ad2SJack F Vogel sector_size = ICH_FLASH_SEG_SIZE_256; 24088cfa0ad2SJack F Vogel iteration = flash_bank_size / ICH_FLASH_SEG_SIZE_256; 24098cfa0ad2SJack F Vogel break; 24108cfa0ad2SJack F Vogel case 1: 24118cfa0ad2SJack F Vogel sector_size = ICH_FLASH_SEG_SIZE_4K; 24129d81738fSJack F Vogel iteration = 1; 24138cfa0ad2SJack F Vogel break; 24148cfa0ad2SJack F Vogel case 2: 24158cfa0ad2SJack F Vogel sector_size = ICH_FLASH_SEG_SIZE_8K; 24168bd0025fSJack F Vogel iteration = 1; 24178cfa0ad2SJack F Vogel break; 24188cfa0ad2SJack F Vogel case 3: 24198cfa0ad2SJack F Vogel sector_size = ICH_FLASH_SEG_SIZE_64K; 24209d81738fSJack F Vogel iteration = 1; 24218cfa0ad2SJack F Vogel break; 24228cfa0ad2SJack F Vogel default: 24238cfa0ad2SJack F Vogel ret_val = -E1000_ERR_NVM; 24248cfa0ad2SJack F Vogel goto out; 24258cfa0ad2SJack F Vogel } 24268cfa0ad2SJack F Vogel 24278cfa0ad2SJack F Vogel /* Start with the base address, then add the sector offset. */ 24288cfa0ad2SJack F Vogel flash_linear_addr = hw->nvm.flash_base_addr; 24294edd8523SJack F Vogel flash_linear_addr += (bank) ? flash_bank_size : 0; 24308cfa0ad2SJack F Vogel 24318cfa0ad2SJack F Vogel for (j = 0; j < iteration ; j++) { 24328cfa0ad2SJack F Vogel do { 24338cfa0ad2SJack F Vogel /* Steps */ 24348cfa0ad2SJack F Vogel ret_val = e1000_flash_cycle_init_ich8lan(hw); 24358cfa0ad2SJack F Vogel if (ret_val) 24368cfa0ad2SJack F Vogel goto out; 24378cfa0ad2SJack F Vogel 24388cfa0ad2SJack F Vogel /* 24398cfa0ad2SJack F Vogel * Write a value 11 (block Erase) in Flash 24408cfa0ad2SJack F Vogel * Cycle field in hw flash control 24418cfa0ad2SJack F Vogel */ 24428cfa0ad2SJack F Vogel hsflctl.regval = E1000_READ_FLASH_REG16(hw, 24438cfa0ad2SJack F Vogel ICH_FLASH_HSFCTL); 24448cfa0ad2SJack F Vogel hsflctl.hsf_ctrl.flcycle = ICH_CYCLE_ERASE; 2445daf9197cSJack F Vogel E1000_WRITE_FLASH_REG16(hw, ICH_FLASH_HSFCTL, 24468cfa0ad2SJack F Vogel hsflctl.regval); 24478cfa0ad2SJack F Vogel 24488cfa0ad2SJack F Vogel /* 24498cfa0ad2SJack F Vogel * Write the last 24 bits of an index within the 24508cfa0ad2SJack F Vogel * block into Flash Linear address field in Flash 24518cfa0ad2SJack F Vogel * Address. 24528cfa0ad2SJack F Vogel */ 24538cfa0ad2SJack F Vogel flash_linear_addr += (j * sector_size); 2454daf9197cSJack F Vogel E1000_WRITE_FLASH_REG(hw, ICH_FLASH_FADDR, 24558cfa0ad2SJack F Vogel flash_linear_addr); 24568cfa0ad2SJack F Vogel 24578cfa0ad2SJack F Vogel ret_val = e1000_flash_cycle_ich8lan(hw, 24588cfa0ad2SJack F Vogel ICH_FLASH_ERASE_COMMAND_TIMEOUT); 2459daf9197cSJack F Vogel if (ret_val == E1000_SUCCESS) 24608cfa0ad2SJack F Vogel break; 2461daf9197cSJack F Vogel 24628cfa0ad2SJack F Vogel /* 24638cfa0ad2SJack F Vogel * Check if FCERR is set to 1. If 1, 24648cfa0ad2SJack F Vogel * clear it and try the whole sequence 24658cfa0ad2SJack F Vogel * a few more times else Done 24668cfa0ad2SJack F Vogel */ 24678cfa0ad2SJack F Vogel hsfsts.regval = E1000_READ_FLASH_REG16(hw, 24688cfa0ad2SJack F Vogel ICH_FLASH_HSFSTS); 2469daf9197cSJack F Vogel if (hsfsts.hsf_status.flcerr == 1) 2470daf9197cSJack F Vogel /* repeat for some time before giving up */ 24718cfa0ad2SJack F Vogel continue; 2472daf9197cSJack F Vogel else if (hsfsts.hsf_status.flcdone == 0) 24738cfa0ad2SJack F Vogel goto out; 24748cfa0ad2SJack F Vogel } while (++count < ICH_FLASH_CYCLE_REPEAT_COUNT); 24758cfa0ad2SJack F Vogel } 24768cfa0ad2SJack F Vogel 24778cfa0ad2SJack F Vogel out: 24788cfa0ad2SJack F Vogel return ret_val; 24798cfa0ad2SJack F Vogel } 24808cfa0ad2SJack F Vogel 24818cfa0ad2SJack F Vogel /** 24828cfa0ad2SJack F Vogel * e1000_valid_led_default_ich8lan - Set the default LED settings 24838cfa0ad2SJack F Vogel * @hw: pointer to the HW structure 24848cfa0ad2SJack F Vogel * @data: Pointer to the LED settings 24858cfa0ad2SJack F Vogel * 24868cfa0ad2SJack F Vogel * Reads the LED default settings from the NVM to data. If the NVM LED 24878cfa0ad2SJack F Vogel * settings is all 0's or F's, set the LED default to a valid LED default 24888cfa0ad2SJack F Vogel * setting. 24898cfa0ad2SJack F Vogel **/ 24908cfa0ad2SJack F Vogel static s32 e1000_valid_led_default_ich8lan(struct e1000_hw *hw, u16 *data) 24918cfa0ad2SJack F Vogel { 24928cfa0ad2SJack F Vogel s32 ret_val; 24938cfa0ad2SJack F Vogel 24948cfa0ad2SJack F Vogel DEBUGFUNC("e1000_valid_led_default_ich8lan"); 24958cfa0ad2SJack F Vogel 24968cfa0ad2SJack F Vogel ret_val = hw->nvm.ops.read(hw, NVM_ID_LED_SETTINGS, 1, data); 24978cfa0ad2SJack F Vogel if (ret_val) { 24988cfa0ad2SJack F Vogel DEBUGOUT("NVM Read Error\n"); 24998cfa0ad2SJack F Vogel goto out; 25008cfa0ad2SJack F Vogel } 25018cfa0ad2SJack F Vogel 25028cfa0ad2SJack F Vogel if (*data == ID_LED_RESERVED_0000 || 25038cfa0ad2SJack F Vogel *data == ID_LED_RESERVED_FFFF) 25048cfa0ad2SJack F Vogel *data = ID_LED_DEFAULT_ICH8LAN; 25058cfa0ad2SJack F Vogel 25068cfa0ad2SJack F Vogel out: 25078cfa0ad2SJack F Vogel return ret_val; 25088cfa0ad2SJack F Vogel } 25098cfa0ad2SJack F Vogel 25108cfa0ad2SJack F Vogel /** 25119d81738fSJack F Vogel * e1000_id_led_init_pchlan - store LED configurations 25129d81738fSJack F Vogel * @hw: pointer to the HW structure 25139d81738fSJack F Vogel * 25149d81738fSJack F Vogel * PCH does not control LEDs via the LEDCTL register, rather it uses 25159d81738fSJack F Vogel * the PHY LED configuration register. 25169d81738fSJack F Vogel * 25179d81738fSJack F Vogel * PCH also does not have an "always on" or "always off" mode which 25189d81738fSJack F Vogel * complicates the ID feature. Instead of using the "on" mode to indicate 25199d81738fSJack F Vogel * in ledctl_mode2 the LEDs to use for ID (see e1000_id_led_init_generic()), 25209d81738fSJack F Vogel * use "link_up" mode. The LEDs will still ID on request if there is no 25219d81738fSJack F Vogel * link based on logic in e1000_led_[on|off]_pchlan(). 25229d81738fSJack F Vogel **/ 25239d81738fSJack F Vogel static s32 e1000_id_led_init_pchlan(struct e1000_hw *hw) 25249d81738fSJack F Vogel { 25259d81738fSJack F Vogel struct e1000_mac_info *mac = &hw->mac; 25269d81738fSJack F Vogel s32 ret_val; 25279d81738fSJack F Vogel const u32 ledctl_on = E1000_LEDCTL_MODE_LINK_UP; 25289d81738fSJack F Vogel const u32 ledctl_off = E1000_LEDCTL_MODE_LINK_UP | E1000_PHY_LED0_IVRT; 25299d81738fSJack F Vogel u16 data, i, temp, shift; 25309d81738fSJack F Vogel 25319d81738fSJack F Vogel DEBUGFUNC("e1000_id_led_init_pchlan"); 25329d81738fSJack F Vogel 25339d81738fSJack F Vogel /* Get default ID LED modes */ 25349d81738fSJack F Vogel ret_val = hw->nvm.ops.valid_led_default(hw, &data); 25359d81738fSJack F Vogel if (ret_val) 25369d81738fSJack F Vogel goto out; 25379d81738fSJack F Vogel 25389d81738fSJack F Vogel mac->ledctl_default = E1000_READ_REG(hw, E1000_LEDCTL); 25399d81738fSJack F Vogel mac->ledctl_mode1 = mac->ledctl_default; 25409d81738fSJack F Vogel mac->ledctl_mode2 = mac->ledctl_default; 25419d81738fSJack F Vogel 25429d81738fSJack F Vogel for (i = 0; i < 4; i++) { 25439d81738fSJack F Vogel temp = (data >> (i << 2)) & E1000_LEDCTL_LED0_MODE_MASK; 25449d81738fSJack F Vogel shift = (i * 5); 25459d81738fSJack F Vogel switch (temp) { 25469d81738fSJack F Vogel case ID_LED_ON1_DEF2: 25479d81738fSJack F Vogel case ID_LED_ON1_ON2: 25489d81738fSJack F Vogel case ID_LED_ON1_OFF2: 25499d81738fSJack F Vogel mac->ledctl_mode1 &= ~(E1000_PHY_LED0_MASK << shift); 25509d81738fSJack F Vogel mac->ledctl_mode1 |= (ledctl_on << shift); 25519d81738fSJack F Vogel break; 25529d81738fSJack F Vogel case ID_LED_OFF1_DEF2: 25539d81738fSJack F Vogel case ID_LED_OFF1_ON2: 25549d81738fSJack F Vogel case ID_LED_OFF1_OFF2: 25559d81738fSJack F Vogel mac->ledctl_mode1 &= ~(E1000_PHY_LED0_MASK << shift); 25569d81738fSJack F Vogel mac->ledctl_mode1 |= (ledctl_off << shift); 25579d81738fSJack F Vogel break; 25589d81738fSJack F Vogel default: 25599d81738fSJack F Vogel /* Do nothing */ 25609d81738fSJack F Vogel break; 25619d81738fSJack F Vogel } 25629d81738fSJack F Vogel switch (temp) { 25639d81738fSJack F Vogel case ID_LED_DEF1_ON2: 25649d81738fSJack F Vogel case ID_LED_ON1_ON2: 25659d81738fSJack F Vogel case ID_LED_OFF1_ON2: 25669d81738fSJack F Vogel mac->ledctl_mode2 &= ~(E1000_PHY_LED0_MASK << shift); 25679d81738fSJack F Vogel mac->ledctl_mode2 |= (ledctl_on << shift); 25689d81738fSJack F Vogel break; 25699d81738fSJack F Vogel case ID_LED_DEF1_OFF2: 25709d81738fSJack F Vogel case ID_LED_ON1_OFF2: 25719d81738fSJack F Vogel case ID_LED_OFF1_OFF2: 25729d81738fSJack F Vogel mac->ledctl_mode2 &= ~(E1000_PHY_LED0_MASK << shift); 25739d81738fSJack F Vogel mac->ledctl_mode2 |= (ledctl_off << shift); 25749d81738fSJack F Vogel break; 25759d81738fSJack F Vogel default: 25769d81738fSJack F Vogel /* Do nothing */ 25779d81738fSJack F Vogel break; 25789d81738fSJack F Vogel } 25799d81738fSJack F Vogel } 25809d81738fSJack F Vogel 25819d81738fSJack F Vogel out: 25829d81738fSJack F Vogel return ret_val; 25839d81738fSJack F Vogel } 25849d81738fSJack F Vogel 25859d81738fSJack F Vogel /** 25868cfa0ad2SJack F Vogel * e1000_get_bus_info_ich8lan - Get/Set the bus type and width 25878cfa0ad2SJack F Vogel * @hw: pointer to the HW structure 25888cfa0ad2SJack F Vogel * 25898cfa0ad2SJack F Vogel * ICH8 use the PCI Express bus, but does not contain a PCI Express Capability 25908cfa0ad2SJack F Vogel * register, so the the bus width is hard coded. 25918cfa0ad2SJack F Vogel **/ 25928cfa0ad2SJack F Vogel static s32 e1000_get_bus_info_ich8lan(struct e1000_hw *hw) 25938cfa0ad2SJack F Vogel { 25948cfa0ad2SJack F Vogel struct e1000_bus_info *bus = &hw->bus; 25958cfa0ad2SJack F Vogel s32 ret_val; 25968cfa0ad2SJack F Vogel 25978cfa0ad2SJack F Vogel DEBUGFUNC("e1000_get_bus_info_ich8lan"); 25988cfa0ad2SJack F Vogel 25998cfa0ad2SJack F Vogel ret_val = e1000_get_bus_info_pcie_generic(hw); 26008cfa0ad2SJack F Vogel 26018cfa0ad2SJack F Vogel /* 26028cfa0ad2SJack F Vogel * ICH devices are "PCI Express"-ish. They have 26038cfa0ad2SJack F Vogel * a configuration space, but do not contain 26048cfa0ad2SJack F Vogel * PCI Express Capability registers, so bus width 26058cfa0ad2SJack F Vogel * must be hardcoded. 26068cfa0ad2SJack F Vogel */ 26078cfa0ad2SJack F Vogel if (bus->width == e1000_bus_width_unknown) 26088cfa0ad2SJack F Vogel bus->width = e1000_bus_width_pcie_x1; 26098cfa0ad2SJack F Vogel 26108cfa0ad2SJack F Vogel return ret_val; 26118cfa0ad2SJack F Vogel } 26128cfa0ad2SJack F Vogel 26138cfa0ad2SJack F Vogel /** 26148cfa0ad2SJack F Vogel * e1000_reset_hw_ich8lan - Reset the hardware 26158cfa0ad2SJack F Vogel * @hw: pointer to the HW structure 26168cfa0ad2SJack F Vogel * 26178cfa0ad2SJack F Vogel * Does a full reset of the hardware which includes a reset of the PHY and 26188cfa0ad2SJack F Vogel * MAC. 26198cfa0ad2SJack F Vogel **/ 26208cfa0ad2SJack F Vogel static s32 e1000_reset_hw_ich8lan(struct e1000_hw *hw) 26218cfa0ad2SJack F Vogel { 26224edd8523SJack F Vogel struct e1000_dev_spec_ich8lan *dev_spec = &hw->dev_spec.ich8lan; 26234edd8523SJack F Vogel u16 reg; 26248cfa0ad2SJack F Vogel u32 ctrl, icr, kab; 26258cfa0ad2SJack F Vogel s32 ret_val; 26268cfa0ad2SJack F Vogel 26278cfa0ad2SJack F Vogel DEBUGFUNC("e1000_reset_hw_ich8lan"); 26288cfa0ad2SJack F Vogel 26298cfa0ad2SJack F Vogel /* 26308cfa0ad2SJack F Vogel * Prevent the PCI-E bus from sticking if there is no TLP connection 26318cfa0ad2SJack F Vogel * on the last TLP read/write transaction when MAC is reset. 26328cfa0ad2SJack F Vogel */ 26338cfa0ad2SJack F Vogel ret_val = e1000_disable_pcie_master_generic(hw); 2634daf9197cSJack F Vogel if (ret_val) 26358cfa0ad2SJack F Vogel DEBUGOUT("PCI-E Master disable polling has failed.\n"); 26368cfa0ad2SJack F Vogel 26378cfa0ad2SJack F Vogel DEBUGOUT("Masking off all interrupts\n"); 26388cfa0ad2SJack F Vogel E1000_WRITE_REG(hw, E1000_IMC, 0xffffffff); 26398cfa0ad2SJack F Vogel 26408cfa0ad2SJack F Vogel /* 26418cfa0ad2SJack F Vogel * Disable the Transmit and Receive units. Then delay to allow 26428cfa0ad2SJack F Vogel * any pending transactions to complete before we hit the MAC 26438cfa0ad2SJack F Vogel * with the global reset. 26448cfa0ad2SJack F Vogel */ 26458cfa0ad2SJack F Vogel E1000_WRITE_REG(hw, E1000_RCTL, 0); 26468cfa0ad2SJack F Vogel E1000_WRITE_REG(hw, E1000_TCTL, E1000_TCTL_PSP); 26478cfa0ad2SJack F Vogel E1000_WRITE_FLUSH(hw); 26488cfa0ad2SJack F Vogel 26498cfa0ad2SJack F Vogel msec_delay(10); 26508cfa0ad2SJack F Vogel 26518cfa0ad2SJack F Vogel /* Workaround for ICH8 bit corruption issue in FIFO memory */ 26528cfa0ad2SJack F Vogel if (hw->mac.type == e1000_ich8lan) { 26538cfa0ad2SJack F Vogel /* Set Tx and Rx buffer allocation to 8k apiece. */ 26548cfa0ad2SJack F Vogel E1000_WRITE_REG(hw, E1000_PBA, E1000_PBA_8K); 26558cfa0ad2SJack F Vogel /* Set Packet Buffer Size to 16k. */ 26568cfa0ad2SJack F Vogel E1000_WRITE_REG(hw, E1000_PBS, E1000_PBS_16K); 26578cfa0ad2SJack F Vogel } 26588cfa0ad2SJack F Vogel 26594edd8523SJack F Vogel if (hw->mac.type == e1000_pchlan) { 26604edd8523SJack F Vogel /* Save the NVM K1 bit setting*/ 26614edd8523SJack F Vogel ret_val = e1000_read_nvm(hw, E1000_NVM_K1_CONFIG, 1, ®); 26624edd8523SJack F Vogel if (ret_val) 26634edd8523SJack F Vogel return ret_val; 26644edd8523SJack F Vogel 26654edd8523SJack F Vogel if (reg & E1000_NVM_K1_ENABLE) 26664edd8523SJack F Vogel dev_spec->nvm_k1_enabled = TRUE; 26674edd8523SJack F Vogel else 26684edd8523SJack F Vogel dev_spec->nvm_k1_enabled = FALSE; 26694edd8523SJack F Vogel } 26704edd8523SJack F Vogel 26718cfa0ad2SJack F Vogel ctrl = E1000_READ_REG(hw, E1000_CTRL); 26728cfa0ad2SJack F Vogel 26738cfa0ad2SJack F Vogel if (!hw->phy.ops.check_reset_block(hw) && !hw->phy.reset_disable) { 26749d81738fSJack F Vogel /* Clear PHY Reset Asserted bit */ 26759d81738fSJack F Vogel if (hw->mac.type >= e1000_pchlan) { 26769d81738fSJack F Vogel u32 status = E1000_READ_REG(hw, E1000_STATUS); 26779d81738fSJack F Vogel E1000_WRITE_REG(hw, E1000_STATUS, status & 26789d81738fSJack F Vogel ~E1000_STATUS_PHYRA); 26799d81738fSJack F Vogel } 26809d81738fSJack F Vogel 26818cfa0ad2SJack F Vogel /* 26828cfa0ad2SJack F Vogel * PHY HW reset requires MAC CORE reset at the same 26838cfa0ad2SJack F Vogel * time to make sure the interface between MAC and the 26848cfa0ad2SJack F Vogel * external PHY is reset. 26858cfa0ad2SJack F Vogel */ 26868cfa0ad2SJack F Vogel ctrl |= E1000_CTRL_PHY_RST; 26878cfa0ad2SJack F Vogel } 26888cfa0ad2SJack F Vogel ret_val = e1000_acquire_swflag_ich8lan(hw); 2689daf9197cSJack F Vogel DEBUGOUT("Issuing a global reset to ich8lan\n"); 26908cfa0ad2SJack F Vogel E1000_WRITE_REG(hw, E1000_CTRL, (ctrl | E1000_CTRL_RST)); 26918cfa0ad2SJack F Vogel msec_delay(20); 26928cfa0ad2SJack F Vogel 26939d81738fSJack F Vogel if (!ret_val) 26949d81738fSJack F Vogel e1000_release_swflag_ich8lan(hw); 26959d81738fSJack F Vogel 2696a69ed8dfSJack F Vogel /* Perform any necessary post-reset workarounds */ 2697a69ed8dfSJack F Vogel switch (hw->mac.type) { 2698a69ed8dfSJack F Vogel case e1000_pchlan: 2699a69ed8dfSJack F Vogel ret_val = e1000_hv_phy_workarounds_ich8lan(hw); 2700a69ed8dfSJack F Vogel if (ret_val) 2701a69ed8dfSJack F Vogel goto out; 2702a69ed8dfSJack F Vogel break; 2703a69ed8dfSJack F Vogel default: 2704a69ed8dfSJack F Vogel break; 2705a69ed8dfSJack F Vogel } 2706a69ed8dfSJack F Vogel 27079d81738fSJack F Vogel if (ctrl & E1000_CTRL_PHY_RST) 27089d81738fSJack F Vogel ret_val = hw->phy.ops.get_cfg_done(hw); 27099d81738fSJack F Vogel 27109d81738fSJack F Vogel if (hw->mac.type >= e1000_ich10lan) { 27119d81738fSJack F Vogel e1000_lan_init_done_ich8lan(hw); 27129d81738fSJack F Vogel } else { 27138cfa0ad2SJack F Vogel ret_val = e1000_get_auto_rd_done_generic(hw); 27148cfa0ad2SJack F Vogel if (ret_val) { 27158cfa0ad2SJack F Vogel /* 27168cfa0ad2SJack F Vogel * When auto config read does not complete, do not 27178cfa0ad2SJack F Vogel * return with an error. This can happen in situations 27188cfa0ad2SJack F Vogel * where there is no eeprom and prevents getting link. 27198cfa0ad2SJack F Vogel */ 27208cfa0ad2SJack F Vogel DEBUGOUT("Auto Read Done did not complete\n"); 27218cfa0ad2SJack F Vogel } 27229d81738fSJack F Vogel } 27238ec87fc5SJack F Vogel /* Dummy read to clear the phy wakeup bit after lcd reset */ 27244edd8523SJack F Vogel if (hw->mac.type == e1000_pchlan) 27254edd8523SJack F Vogel hw->phy.ops.read_reg(hw, BM_WUC, ®); 27264edd8523SJack F Vogel 27274edd8523SJack F Vogel ret_val = e1000_sw_lcd_config_ich8lan(hw); 27284edd8523SJack F Vogel if (ret_val) 27294edd8523SJack F Vogel goto out; 27304edd8523SJack F Vogel 27314edd8523SJack F Vogel ret_val = e1000_oem_bits_config_ich8lan(hw, TRUE); 27324edd8523SJack F Vogel if (ret_val) 27334edd8523SJack F Vogel goto out; 27344edd8523SJack F Vogel /* 27354edd8523SJack F Vogel * For PCH, this write will make sure that any noise 27364edd8523SJack F Vogel * will be detected as a CRC error and be dropped rather than show up 27374edd8523SJack F Vogel * as a bad packet to the DMA engine. 27384edd8523SJack F Vogel */ 27394edd8523SJack F Vogel if (hw->mac.type == e1000_pchlan) 27404edd8523SJack F Vogel E1000_WRITE_REG(hw, E1000_CRC_OFFSET, 0x65656565); 27418cfa0ad2SJack F Vogel 27428cfa0ad2SJack F Vogel E1000_WRITE_REG(hw, E1000_IMC, 0xffffffff); 27438cfa0ad2SJack F Vogel icr = E1000_READ_REG(hw, E1000_ICR); 27448cfa0ad2SJack F Vogel 27458cfa0ad2SJack F Vogel kab = E1000_READ_REG(hw, E1000_KABGTXD); 27468cfa0ad2SJack F Vogel kab |= E1000_KABGTXD_BGSQLBIAS; 27478cfa0ad2SJack F Vogel E1000_WRITE_REG(hw, E1000_KABGTXD, kab); 27488cfa0ad2SJack F Vogel 27494edd8523SJack F Vogel out: 27508cfa0ad2SJack F Vogel return ret_val; 27518cfa0ad2SJack F Vogel } 27528cfa0ad2SJack F Vogel 27538cfa0ad2SJack F Vogel /** 27548cfa0ad2SJack F Vogel * e1000_init_hw_ich8lan - Initialize the hardware 27558cfa0ad2SJack F Vogel * @hw: pointer to the HW structure 27568cfa0ad2SJack F Vogel * 27578cfa0ad2SJack F Vogel * Prepares the hardware for transmit and receive by doing the following: 27588cfa0ad2SJack F Vogel * - initialize hardware bits 27598cfa0ad2SJack F Vogel * - initialize LED identification 27608cfa0ad2SJack F Vogel * - setup receive address registers 27618cfa0ad2SJack F Vogel * - setup flow control 27628cfa0ad2SJack F Vogel * - setup transmit descriptors 27638cfa0ad2SJack F Vogel * - clear statistics 27648cfa0ad2SJack F Vogel **/ 27658cfa0ad2SJack F Vogel static s32 e1000_init_hw_ich8lan(struct e1000_hw *hw) 27668cfa0ad2SJack F Vogel { 27678cfa0ad2SJack F Vogel struct e1000_mac_info *mac = &hw->mac; 27688cfa0ad2SJack F Vogel u32 ctrl_ext, txdctl, snoop; 27698cfa0ad2SJack F Vogel s32 ret_val; 27708cfa0ad2SJack F Vogel u16 i; 27718cfa0ad2SJack F Vogel 27728cfa0ad2SJack F Vogel DEBUGFUNC("e1000_init_hw_ich8lan"); 27738cfa0ad2SJack F Vogel 27748cfa0ad2SJack F Vogel e1000_initialize_hw_bits_ich8lan(hw); 27758cfa0ad2SJack F Vogel 27768cfa0ad2SJack F Vogel /* Initialize identification LED */ 2777d035aa2dSJack F Vogel ret_val = mac->ops.id_led_init(hw); 2778d035aa2dSJack F Vogel if (ret_val) 2779d035aa2dSJack F Vogel DEBUGOUT("Error initializing identification LED\n"); 27804edd8523SJack F Vogel /* This is not fatal and we should not stop init due to this */ 27818cfa0ad2SJack F Vogel 27828cfa0ad2SJack F Vogel /* Setup the receive address. */ 27838cfa0ad2SJack F Vogel e1000_init_rx_addrs_generic(hw, mac->rar_entry_count); 27848cfa0ad2SJack F Vogel 27858cfa0ad2SJack F Vogel /* Zero out the Multicast HASH table */ 27868cfa0ad2SJack F Vogel DEBUGOUT("Zeroing the MTA\n"); 27878cfa0ad2SJack F Vogel for (i = 0; i < mac->mta_reg_count; i++) 27888cfa0ad2SJack F Vogel E1000_WRITE_REG_ARRAY(hw, E1000_MTA, i, 0); 27898cfa0ad2SJack F Vogel 27909d81738fSJack F Vogel /* 27919d81738fSJack F Vogel * The 82578 Rx buffer will stall if wakeup is enabled in host and 27929d81738fSJack F Vogel * the ME. Reading the BM_WUC register will clear the host wakeup bit. 27939d81738fSJack F Vogel * Reset the phy after disabling host wakeup to reset the Rx buffer. 27949d81738fSJack F Vogel */ 27959d81738fSJack F Vogel if (hw->phy.type == e1000_phy_82578) { 27969d81738fSJack F Vogel hw->phy.ops.read_reg(hw, BM_WUC, &i); 27979d81738fSJack F Vogel ret_val = e1000_phy_hw_reset_ich8lan(hw); 27989d81738fSJack F Vogel if (ret_val) 27999d81738fSJack F Vogel return ret_val; 28009d81738fSJack F Vogel } 28019d81738fSJack F Vogel 28028cfa0ad2SJack F Vogel /* Setup link and flow control */ 28038cfa0ad2SJack F Vogel ret_val = mac->ops.setup_link(hw); 28048cfa0ad2SJack F Vogel 28058cfa0ad2SJack F Vogel /* Set the transmit descriptor write-back policy for both queues */ 28068cfa0ad2SJack F Vogel txdctl = E1000_READ_REG(hw, E1000_TXDCTL(0)); 28078cfa0ad2SJack F Vogel txdctl = (txdctl & ~E1000_TXDCTL_WTHRESH) | 28088cfa0ad2SJack F Vogel E1000_TXDCTL_FULL_TX_DESC_WB; 28098cfa0ad2SJack F Vogel txdctl = (txdctl & ~E1000_TXDCTL_PTHRESH) | 28108cfa0ad2SJack F Vogel E1000_TXDCTL_MAX_TX_DESC_PREFETCH; 28118cfa0ad2SJack F Vogel E1000_WRITE_REG(hw, E1000_TXDCTL(0), txdctl); 28128cfa0ad2SJack F Vogel txdctl = E1000_READ_REG(hw, E1000_TXDCTL(1)); 28138cfa0ad2SJack F Vogel txdctl = (txdctl & ~E1000_TXDCTL_WTHRESH) | 28148cfa0ad2SJack F Vogel E1000_TXDCTL_FULL_TX_DESC_WB; 28158cfa0ad2SJack F Vogel txdctl = (txdctl & ~E1000_TXDCTL_PTHRESH) | 28168cfa0ad2SJack F Vogel E1000_TXDCTL_MAX_TX_DESC_PREFETCH; 28178cfa0ad2SJack F Vogel E1000_WRITE_REG(hw, E1000_TXDCTL(1), txdctl); 28188cfa0ad2SJack F Vogel 28198cfa0ad2SJack F Vogel /* 28208cfa0ad2SJack F Vogel * ICH8 has opposite polarity of no_snoop bits. 28218cfa0ad2SJack F Vogel * By default, we should use snoop behavior. 28228cfa0ad2SJack F Vogel */ 28238cfa0ad2SJack F Vogel if (mac->type == e1000_ich8lan) 28248cfa0ad2SJack F Vogel snoop = PCIE_ICH8_SNOOP_ALL; 28258cfa0ad2SJack F Vogel else 28268cfa0ad2SJack F Vogel snoop = (u32) ~(PCIE_NO_SNOOP_ALL); 28278cfa0ad2SJack F Vogel e1000_set_pcie_no_snoop_generic(hw, snoop); 28288cfa0ad2SJack F Vogel 28298cfa0ad2SJack F Vogel ctrl_ext = E1000_READ_REG(hw, E1000_CTRL_EXT); 28308cfa0ad2SJack F Vogel ctrl_ext |= E1000_CTRL_EXT_RO_DIS; 28318cfa0ad2SJack F Vogel E1000_WRITE_REG(hw, E1000_CTRL_EXT, ctrl_ext); 28328cfa0ad2SJack F Vogel 28338cfa0ad2SJack F Vogel /* 28348cfa0ad2SJack F Vogel * Clear all of the statistics registers (clear on read). It is 28358cfa0ad2SJack F Vogel * important that we do this after we have tried to establish link 28368cfa0ad2SJack F Vogel * because the symbol error count will increment wildly if there 28378cfa0ad2SJack F Vogel * is no link. 28388cfa0ad2SJack F Vogel */ 28398cfa0ad2SJack F Vogel e1000_clear_hw_cntrs_ich8lan(hw); 28408cfa0ad2SJack F Vogel 28418cfa0ad2SJack F Vogel return ret_val; 28428cfa0ad2SJack F Vogel } 28438cfa0ad2SJack F Vogel /** 28448cfa0ad2SJack F Vogel * e1000_initialize_hw_bits_ich8lan - Initialize required hardware bits 28458cfa0ad2SJack F Vogel * @hw: pointer to the HW structure 28468cfa0ad2SJack F Vogel * 28478cfa0ad2SJack F Vogel * Sets/Clears required hardware bits necessary for correctly setting up the 28488cfa0ad2SJack F Vogel * hardware for transmit and receive. 28498cfa0ad2SJack F Vogel **/ 28508cfa0ad2SJack F Vogel static void e1000_initialize_hw_bits_ich8lan(struct e1000_hw *hw) 28518cfa0ad2SJack F Vogel { 28528cfa0ad2SJack F Vogel u32 reg; 28538cfa0ad2SJack F Vogel 28548cfa0ad2SJack F Vogel DEBUGFUNC("e1000_initialize_hw_bits_ich8lan"); 28558cfa0ad2SJack F Vogel 28568cfa0ad2SJack F Vogel /* Extended Device Control */ 28578cfa0ad2SJack F Vogel reg = E1000_READ_REG(hw, E1000_CTRL_EXT); 28588cfa0ad2SJack F Vogel reg |= (1 << 22); 28599d81738fSJack F Vogel /* Enable PHY low-power state when MAC is at D3 w/o WoL */ 28609d81738fSJack F Vogel if (hw->mac.type >= e1000_pchlan) 28619d81738fSJack F Vogel reg |= E1000_CTRL_EXT_PHYPDEN; 28628cfa0ad2SJack F Vogel E1000_WRITE_REG(hw, E1000_CTRL_EXT, reg); 28638cfa0ad2SJack F Vogel 28648cfa0ad2SJack F Vogel /* Transmit Descriptor Control 0 */ 28658cfa0ad2SJack F Vogel reg = E1000_READ_REG(hw, E1000_TXDCTL(0)); 28668cfa0ad2SJack F Vogel reg |= (1 << 22); 28678cfa0ad2SJack F Vogel E1000_WRITE_REG(hw, E1000_TXDCTL(0), reg); 28688cfa0ad2SJack F Vogel 28698cfa0ad2SJack F Vogel /* Transmit Descriptor Control 1 */ 28708cfa0ad2SJack F Vogel reg = E1000_READ_REG(hw, E1000_TXDCTL(1)); 28718cfa0ad2SJack F Vogel reg |= (1 << 22); 28728cfa0ad2SJack F Vogel E1000_WRITE_REG(hw, E1000_TXDCTL(1), reg); 28738cfa0ad2SJack F Vogel 28748cfa0ad2SJack F Vogel /* Transmit Arbitration Control 0 */ 28758cfa0ad2SJack F Vogel reg = E1000_READ_REG(hw, E1000_TARC(0)); 28768cfa0ad2SJack F Vogel if (hw->mac.type == e1000_ich8lan) 28778cfa0ad2SJack F Vogel reg |= (1 << 28) | (1 << 29); 28788cfa0ad2SJack F Vogel reg |= (1 << 23) | (1 << 24) | (1 << 26) | (1 << 27); 28798cfa0ad2SJack F Vogel E1000_WRITE_REG(hw, E1000_TARC(0), reg); 28808cfa0ad2SJack F Vogel 28818cfa0ad2SJack F Vogel /* Transmit Arbitration Control 1 */ 28828cfa0ad2SJack F Vogel reg = E1000_READ_REG(hw, E1000_TARC(1)); 28838cfa0ad2SJack F Vogel if (E1000_READ_REG(hw, E1000_TCTL) & E1000_TCTL_MULR) 28848cfa0ad2SJack F Vogel reg &= ~(1 << 28); 28858cfa0ad2SJack F Vogel else 28868cfa0ad2SJack F Vogel reg |= (1 << 28); 28878cfa0ad2SJack F Vogel reg |= (1 << 24) | (1 << 26) | (1 << 30); 28888cfa0ad2SJack F Vogel E1000_WRITE_REG(hw, E1000_TARC(1), reg); 28898cfa0ad2SJack F Vogel 28908cfa0ad2SJack F Vogel /* Device Status */ 28918cfa0ad2SJack F Vogel if (hw->mac.type == e1000_ich8lan) { 28928cfa0ad2SJack F Vogel reg = E1000_READ_REG(hw, E1000_STATUS); 28938cfa0ad2SJack F Vogel reg &= ~(1 << 31); 28948cfa0ad2SJack F Vogel E1000_WRITE_REG(hw, E1000_STATUS, reg); 28958cfa0ad2SJack F Vogel } 28968cfa0ad2SJack F Vogel 28978ec87fc5SJack F Vogel /* 28988ec87fc5SJack F Vogel * work-around descriptor data corruption issue during nfs v2 udp 28998ec87fc5SJack F Vogel * traffic, just disable the nfs filtering capability 29008ec87fc5SJack F Vogel */ 29018ec87fc5SJack F Vogel reg = E1000_READ_REG(hw, E1000_RFCTL); 29028ec87fc5SJack F Vogel reg |= (E1000_RFCTL_NFSW_DIS | E1000_RFCTL_NFSR_DIS); 29038ec87fc5SJack F Vogel E1000_WRITE_REG(hw, E1000_RFCTL, reg); 29048ec87fc5SJack F Vogel 29058cfa0ad2SJack F Vogel return; 29068cfa0ad2SJack F Vogel } 29078cfa0ad2SJack F Vogel 29088cfa0ad2SJack F Vogel /** 29098cfa0ad2SJack F Vogel * e1000_setup_link_ich8lan - Setup flow control and link settings 29108cfa0ad2SJack F Vogel * @hw: pointer to the HW structure 29118cfa0ad2SJack F Vogel * 29128cfa0ad2SJack F Vogel * Determines which flow control settings to use, then configures flow 29138cfa0ad2SJack F Vogel * control. Calls the appropriate media-specific link configuration 29148cfa0ad2SJack F Vogel * function. Assuming the adapter has a valid link partner, a valid link 29158cfa0ad2SJack F Vogel * should be established. Assumes the hardware has previously been reset 29168cfa0ad2SJack F Vogel * and the transmitter and receiver are not enabled. 29178cfa0ad2SJack F Vogel **/ 29188cfa0ad2SJack F Vogel static s32 e1000_setup_link_ich8lan(struct e1000_hw *hw) 29198cfa0ad2SJack F Vogel { 29208cfa0ad2SJack F Vogel s32 ret_val = E1000_SUCCESS; 29218cfa0ad2SJack F Vogel 29228cfa0ad2SJack F Vogel DEBUGFUNC("e1000_setup_link_ich8lan"); 29238cfa0ad2SJack F Vogel 29248cfa0ad2SJack F Vogel if (hw->phy.ops.check_reset_block(hw)) 29258cfa0ad2SJack F Vogel goto out; 29268cfa0ad2SJack F Vogel 29278cfa0ad2SJack F Vogel /* 29288cfa0ad2SJack F Vogel * ICH parts do not have a word in the NVM to determine 29298cfa0ad2SJack F Vogel * the default flow control setting, so we explicitly 29308cfa0ad2SJack F Vogel * set it to full. 29318cfa0ad2SJack F Vogel */ 2932daf9197cSJack F Vogel if (hw->fc.requested_mode == e1000_fc_default) 2933daf9197cSJack F Vogel hw->fc.requested_mode = e1000_fc_full; 29348cfa0ad2SJack F Vogel 2935daf9197cSJack F Vogel /* 2936daf9197cSJack F Vogel * Save off the requested flow control mode for use later. Depending 2937daf9197cSJack F Vogel * on the link partner's capabilities, we may or may not use this mode. 2938daf9197cSJack F Vogel */ 2939daf9197cSJack F Vogel hw->fc.current_mode = hw->fc.requested_mode; 29408cfa0ad2SJack F Vogel 2941daf9197cSJack F Vogel DEBUGOUT1("After fix-ups FlowControl is now = %x\n", 2942daf9197cSJack F Vogel hw->fc.current_mode); 29438cfa0ad2SJack F Vogel 29448cfa0ad2SJack F Vogel /* Continue to configure the copper link. */ 29458cfa0ad2SJack F Vogel ret_val = hw->mac.ops.setup_physical_interface(hw); 29468cfa0ad2SJack F Vogel if (ret_val) 29478cfa0ad2SJack F Vogel goto out; 29488cfa0ad2SJack F Vogel 29498cfa0ad2SJack F Vogel E1000_WRITE_REG(hw, E1000_FCTTV, hw->fc.pause_time); 29509d81738fSJack F Vogel if ((hw->phy.type == e1000_phy_82578) || 29519d81738fSJack F Vogel (hw->phy.type == e1000_phy_82577)) { 29529d81738fSJack F Vogel ret_val = hw->phy.ops.write_reg(hw, 29539d81738fSJack F Vogel PHY_REG(BM_PORT_CTRL_PAGE, 27), 29549d81738fSJack F Vogel hw->fc.pause_time); 29559d81738fSJack F Vogel if (ret_val) 29569d81738fSJack F Vogel goto out; 29579d81738fSJack F Vogel } 29588cfa0ad2SJack F Vogel 29598cfa0ad2SJack F Vogel ret_val = e1000_set_fc_watermarks_generic(hw); 29608cfa0ad2SJack F Vogel 29618cfa0ad2SJack F Vogel out: 29628cfa0ad2SJack F Vogel return ret_val; 29638cfa0ad2SJack F Vogel } 29648cfa0ad2SJack F Vogel 29658cfa0ad2SJack F Vogel /** 29668cfa0ad2SJack F Vogel * e1000_setup_copper_link_ich8lan - Configure MAC/PHY interface 29678cfa0ad2SJack F Vogel * @hw: pointer to the HW structure 29688cfa0ad2SJack F Vogel * 29698cfa0ad2SJack F Vogel * Configures the kumeran interface to the PHY to wait the appropriate time 29708cfa0ad2SJack F Vogel * when polling the PHY, then call the generic setup_copper_link to finish 29718cfa0ad2SJack F Vogel * configuring the copper link. 29728cfa0ad2SJack F Vogel **/ 29738cfa0ad2SJack F Vogel static s32 e1000_setup_copper_link_ich8lan(struct e1000_hw *hw) 29748cfa0ad2SJack F Vogel { 29758cfa0ad2SJack F Vogel u32 ctrl; 29768cfa0ad2SJack F Vogel s32 ret_val; 29778cfa0ad2SJack F Vogel u16 reg_data; 29788cfa0ad2SJack F Vogel 29798cfa0ad2SJack F Vogel DEBUGFUNC("e1000_setup_copper_link_ich8lan"); 29808cfa0ad2SJack F Vogel 29818cfa0ad2SJack F Vogel ctrl = E1000_READ_REG(hw, E1000_CTRL); 29828cfa0ad2SJack F Vogel ctrl |= E1000_CTRL_SLU; 29838cfa0ad2SJack F Vogel ctrl &= ~(E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX); 29848cfa0ad2SJack F Vogel E1000_WRITE_REG(hw, E1000_CTRL, ctrl); 29858cfa0ad2SJack F Vogel 29868cfa0ad2SJack F Vogel /* 29878cfa0ad2SJack F Vogel * Set the mac to wait the maximum time between each iteration 29888cfa0ad2SJack F Vogel * and increase the max iterations when polling the phy; 29898cfa0ad2SJack F Vogel * this fixes erroneous timeouts at 10Mbps. 29908cfa0ad2SJack F Vogel */ 29914edd8523SJack F Vogel ret_val = e1000_write_kmrn_reg_generic(hw, E1000_KMRNCTRLSTA_TIMEOUTS, 29928cfa0ad2SJack F Vogel 0xFFFF); 29938cfa0ad2SJack F Vogel if (ret_val) 29948cfa0ad2SJack F Vogel goto out; 29959d81738fSJack F Vogel ret_val = e1000_read_kmrn_reg_generic(hw, 29969d81738fSJack F Vogel E1000_KMRNCTRLSTA_INBAND_PARAM, 29978cfa0ad2SJack F Vogel ®_data); 29988cfa0ad2SJack F Vogel if (ret_val) 29998cfa0ad2SJack F Vogel goto out; 30008cfa0ad2SJack F Vogel reg_data |= 0x3F; 30019d81738fSJack F Vogel ret_val = e1000_write_kmrn_reg_generic(hw, 30029d81738fSJack F Vogel E1000_KMRNCTRLSTA_INBAND_PARAM, 30038cfa0ad2SJack F Vogel reg_data); 30048cfa0ad2SJack F Vogel if (ret_val) 30058cfa0ad2SJack F Vogel goto out; 30068cfa0ad2SJack F Vogel 3007d035aa2dSJack F Vogel switch (hw->phy.type) { 3008d035aa2dSJack F Vogel case e1000_phy_igp_3: 30098cfa0ad2SJack F Vogel ret_val = e1000_copper_link_setup_igp(hw); 30108cfa0ad2SJack F Vogel if (ret_val) 30118cfa0ad2SJack F Vogel goto out; 3012d035aa2dSJack F Vogel break; 3013d035aa2dSJack F Vogel case e1000_phy_bm: 30149d81738fSJack F Vogel case e1000_phy_82578: 30158cfa0ad2SJack F Vogel ret_val = e1000_copper_link_setup_m88(hw); 30168cfa0ad2SJack F Vogel if (ret_val) 30178cfa0ad2SJack F Vogel goto out; 3018d035aa2dSJack F Vogel break; 30199d81738fSJack F Vogel case e1000_phy_82577: 30209d81738fSJack F Vogel ret_val = e1000_copper_link_setup_82577(hw); 30219d81738fSJack F Vogel if (ret_val) 30229d81738fSJack F Vogel goto out; 30239d81738fSJack F Vogel break; 3024d035aa2dSJack F Vogel case e1000_phy_ife: 30258cfa0ad2SJack F Vogel ret_val = hw->phy.ops.read_reg(hw, IFE_PHY_MDIX_CONTROL, 30268cfa0ad2SJack F Vogel ®_data); 30278cfa0ad2SJack F Vogel if (ret_val) 30288cfa0ad2SJack F Vogel goto out; 30298cfa0ad2SJack F Vogel 30308cfa0ad2SJack F Vogel reg_data &= ~IFE_PMC_AUTO_MDIX; 30318cfa0ad2SJack F Vogel 30328cfa0ad2SJack F Vogel switch (hw->phy.mdix) { 30338cfa0ad2SJack F Vogel case 1: 30348cfa0ad2SJack F Vogel reg_data &= ~IFE_PMC_FORCE_MDIX; 30358cfa0ad2SJack F Vogel break; 30368cfa0ad2SJack F Vogel case 2: 30378cfa0ad2SJack F Vogel reg_data |= IFE_PMC_FORCE_MDIX; 30388cfa0ad2SJack F Vogel break; 30398cfa0ad2SJack F Vogel case 0: 30408cfa0ad2SJack F Vogel default: 30418cfa0ad2SJack F Vogel reg_data |= IFE_PMC_AUTO_MDIX; 30428cfa0ad2SJack F Vogel break; 30438cfa0ad2SJack F Vogel } 30448cfa0ad2SJack F Vogel ret_val = hw->phy.ops.write_reg(hw, IFE_PHY_MDIX_CONTROL, 30458cfa0ad2SJack F Vogel reg_data); 30468cfa0ad2SJack F Vogel if (ret_val) 30478cfa0ad2SJack F Vogel goto out; 3048d035aa2dSJack F Vogel break; 3049d035aa2dSJack F Vogel default: 3050d035aa2dSJack F Vogel break; 30518cfa0ad2SJack F Vogel } 30528cfa0ad2SJack F Vogel ret_val = e1000_setup_copper_link_generic(hw); 30538cfa0ad2SJack F Vogel 30548cfa0ad2SJack F Vogel out: 30558cfa0ad2SJack F Vogel return ret_val; 30568cfa0ad2SJack F Vogel } 30578cfa0ad2SJack F Vogel 30588cfa0ad2SJack F Vogel /** 30598cfa0ad2SJack F Vogel * e1000_get_link_up_info_ich8lan - Get current link speed and duplex 30608cfa0ad2SJack F Vogel * @hw: pointer to the HW structure 30618cfa0ad2SJack F Vogel * @speed: pointer to store current link speed 30628cfa0ad2SJack F Vogel * @duplex: pointer to store the current link duplex 30638cfa0ad2SJack F Vogel * 30648cfa0ad2SJack F Vogel * Calls the generic get_speed_and_duplex to retrieve the current link 30658cfa0ad2SJack F Vogel * information and then calls the Kumeran lock loss workaround for links at 30668cfa0ad2SJack F Vogel * gigabit speeds. 30678cfa0ad2SJack F Vogel **/ 30688cfa0ad2SJack F Vogel static s32 e1000_get_link_up_info_ich8lan(struct e1000_hw *hw, u16 *speed, 30698cfa0ad2SJack F Vogel u16 *duplex) 30708cfa0ad2SJack F Vogel { 30718cfa0ad2SJack F Vogel s32 ret_val; 30728cfa0ad2SJack F Vogel 30738cfa0ad2SJack F Vogel DEBUGFUNC("e1000_get_link_up_info_ich8lan"); 30748cfa0ad2SJack F Vogel 30758cfa0ad2SJack F Vogel ret_val = e1000_get_speed_and_duplex_copper_generic(hw, speed, duplex); 30768cfa0ad2SJack F Vogel if (ret_val) 30778cfa0ad2SJack F Vogel goto out; 30788cfa0ad2SJack F Vogel 30798cfa0ad2SJack F Vogel if ((hw->mac.type == e1000_ich8lan) && 30808cfa0ad2SJack F Vogel (hw->phy.type == e1000_phy_igp_3) && 30818cfa0ad2SJack F Vogel (*speed == SPEED_1000)) { 30828cfa0ad2SJack F Vogel ret_val = e1000_kmrn_lock_loss_workaround_ich8lan(hw); 30838cfa0ad2SJack F Vogel } 30848cfa0ad2SJack F Vogel 30858cfa0ad2SJack F Vogel out: 30868cfa0ad2SJack F Vogel return ret_val; 30878cfa0ad2SJack F Vogel } 30888cfa0ad2SJack F Vogel 30898cfa0ad2SJack F Vogel /** 30908cfa0ad2SJack F Vogel * e1000_kmrn_lock_loss_workaround_ich8lan - Kumeran workaround 30918cfa0ad2SJack F Vogel * @hw: pointer to the HW structure 30928cfa0ad2SJack F Vogel * 30938cfa0ad2SJack F Vogel * Work-around for 82566 Kumeran PCS lock loss: 30948cfa0ad2SJack F Vogel * On link status change (i.e. PCI reset, speed change) and link is up and 30958cfa0ad2SJack F Vogel * speed is gigabit- 30968cfa0ad2SJack F Vogel * 0) if workaround is optionally disabled do nothing 30978cfa0ad2SJack F Vogel * 1) wait 1ms for Kumeran link to come up 30988cfa0ad2SJack F Vogel * 2) check Kumeran Diagnostic register PCS lock loss bit 30998cfa0ad2SJack F Vogel * 3) if not set the link is locked (all is good), otherwise... 31008cfa0ad2SJack F Vogel * 4) reset the PHY 31018cfa0ad2SJack F Vogel * 5) repeat up to 10 times 31028cfa0ad2SJack F Vogel * Note: this is only called for IGP3 copper when speed is 1gb. 31038cfa0ad2SJack F Vogel **/ 31048cfa0ad2SJack F Vogel static s32 e1000_kmrn_lock_loss_workaround_ich8lan(struct e1000_hw *hw) 31058cfa0ad2SJack F Vogel { 3106daf9197cSJack F Vogel struct e1000_dev_spec_ich8lan *dev_spec = &hw->dev_spec.ich8lan; 31078cfa0ad2SJack F Vogel u32 phy_ctrl; 31088cfa0ad2SJack F Vogel s32 ret_val = E1000_SUCCESS; 31098cfa0ad2SJack F Vogel u16 i, data; 31108cfa0ad2SJack F Vogel bool link; 31118cfa0ad2SJack F Vogel 31128cfa0ad2SJack F Vogel DEBUGFUNC("e1000_kmrn_lock_loss_workaround_ich8lan"); 31138cfa0ad2SJack F Vogel 31148cfa0ad2SJack F Vogel if (!(dev_spec->kmrn_lock_loss_workaround_enabled)) 31158cfa0ad2SJack F Vogel goto out; 31168cfa0ad2SJack F Vogel 31178cfa0ad2SJack F Vogel /* 31188cfa0ad2SJack F Vogel * Make sure link is up before proceeding. If not just return. 31198cfa0ad2SJack F Vogel * Attempting this while link is negotiating fouled up link 31208cfa0ad2SJack F Vogel * stability 31218cfa0ad2SJack F Vogel */ 31228cfa0ad2SJack F Vogel ret_val = e1000_phy_has_link_generic(hw, 1, 0, &link); 31238cfa0ad2SJack F Vogel if (!link) { 31248cfa0ad2SJack F Vogel ret_val = E1000_SUCCESS; 31258cfa0ad2SJack F Vogel goto out; 31268cfa0ad2SJack F Vogel } 31278cfa0ad2SJack F Vogel 31288cfa0ad2SJack F Vogel for (i = 0; i < 10; i++) { 31298cfa0ad2SJack F Vogel /* read once to clear */ 31308cfa0ad2SJack F Vogel ret_val = hw->phy.ops.read_reg(hw, IGP3_KMRN_DIAG, &data); 31318cfa0ad2SJack F Vogel if (ret_val) 31328cfa0ad2SJack F Vogel goto out; 31338cfa0ad2SJack F Vogel /* and again to get new status */ 31348cfa0ad2SJack F Vogel ret_val = hw->phy.ops.read_reg(hw, IGP3_KMRN_DIAG, &data); 31358cfa0ad2SJack F Vogel if (ret_val) 31368cfa0ad2SJack F Vogel goto out; 31378cfa0ad2SJack F Vogel 31388cfa0ad2SJack F Vogel /* check for PCS lock */ 31398cfa0ad2SJack F Vogel if (!(data & IGP3_KMRN_DIAG_PCS_LOCK_LOSS)) { 31408cfa0ad2SJack F Vogel ret_val = E1000_SUCCESS; 31418cfa0ad2SJack F Vogel goto out; 31428cfa0ad2SJack F Vogel } 31438cfa0ad2SJack F Vogel 31448cfa0ad2SJack F Vogel /* Issue PHY reset */ 31458cfa0ad2SJack F Vogel hw->phy.ops.reset(hw); 31468cfa0ad2SJack F Vogel msec_delay_irq(5); 31478cfa0ad2SJack F Vogel } 31488cfa0ad2SJack F Vogel /* Disable GigE link negotiation */ 31498cfa0ad2SJack F Vogel phy_ctrl = E1000_READ_REG(hw, E1000_PHY_CTRL); 31508cfa0ad2SJack F Vogel phy_ctrl |= (E1000_PHY_CTRL_GBE_DISABLE | 31518cfa0ad2SJack F Vogel E1000_PHY_CTRL_NOND0A_GBE_DISABLE); 31528cfa0ad2SJack F Vogel E1000_WRITE_REG(hw, E1000_PHY_CTRL, phy_ctrl); 31538cfa0ad2SJack F Vogel 31548cfa0ad2SJack F Vogel /* 31558cfa0ad2SJack F Vogel * Call gig speed drop workaround on Gig disable before accessing 31568cfa0ad2SJack F Vogel * any PHY registers 31578cfa0ad2SJack F Vogel */ 31588cfa0ad2SJack F Vogel e1000_gig_downshift_workaround_ich8lan(hw); 31598cfa0ad2SJack F Vogel 31608cfa0ad2SJack F Vogel /* unable to acquire PCS lock */ 31618cfa0ad2SJack F Vogel ret_val = -E1000_ERR_PHY; 31628cfa0ad2SJack F Vogel 31638cfa0ad2SJack F Vogel out: 31648cfa0ad2SJack F Vogel return ret_val; 31658cfa0ad2SJack F Vogel } 31668cfa0ad2SJack F Vogel 31678cfa0ad2SJack F Vogel /** 31688cfa0ad2SJack F Vogel * e1000_set_kmrn_lock_loss_workaround_ich8lan - Set Kumeran workaround state 31698cfa0ad2SJack F Vogel * @hw: pointer to the HW structure 31708cfa0ad2SJack F Vogel * @state: boolean value used to set the current Kumeran workaround state 31718cfa0ad2SJack F Vogel * 31728cfa0ad2SJack F Vogel * If ICH8, set the current Kumeran workaround state (enabled - TRUE 31738cfa0ad2SJack F Vogel * /disabled - FALSE). 31748cfa0ad2SJack F Vogel **/ 31758cfa0ad2SJack F Vogel void e1000_set_kmrn_lock_loss_workaround_ich8lan(struct e1000_hw *hw, 31768cfa0ad2SJack F Vogel bool state) 31778cfa0ad2SJack F Vogel { 3178daf9197cSJack F Vogel struct e1000_dev_spec_ich8lan *dev_spec = &hw->dev_spec.ich8lan; 31798cfa0ad2SJack F Vogel 31808cfa0ad2SJack F Vogel DEBUGFUNC("e1000_set_kmrn_lock_loss_workaround_ich8lan"); 31818cfa0ad2SJack F Vogel 31828cfa0ad2SJack F Vogel if (hw->mac.type != e1000_ich8lan) { 31838cfa0ad2SJack F Vogel DEBUGOUT("Workaround applies to ICH8 only.\n"); 3184daf9197cSJack F Vogel return; 31858cfa0ad2SJack F Vogel } 31868cfa0ad2SJack F Vogel 31878cfa0ad2SJack F Vogel dev_spec->kmrn_lock_loss_workaround_enabled = state; 31888cfa0ad2SJack F Vogel 31898cfa0ad2SJack F Vogel return; 31908cfa0ad2SJack F Vogel } 31918cfa0ad2SJack F Vogel 31928cfa0ad2SJack F Vogel /** 31938cfa0ad2SJack F Vogel * e1000_ipg3_phy_powerdown_workaround_ich8lan - Power down workaround on D3 31948cfa0ad2SJack F Vogel * @hw: pointer to the HW structure 31958cfa0ad2SJack F Vogel * 31968cfa0ad2SJack F Vogel * Workaround for 82566 power-down on D3 entry: 31978cfa0ad2SJack F Vogel * 1) disable gigabit link 31988cfa0ad2SJack F Vogel * 2) write VR power-down enable 31998cfa0ad2SJack F Vogel * 3) read it back 32008cfa0ad2SJack F Vogel * Continue if successful, else issue LCD reset and repeat 32018cfa0ad2SJack F Vogel **/ 32028cfa0ad2SJack F Vogel void e1000_igp3_phy_powerdown_workaround_ich8lan(struct e1000_hw *hw) 32038cfa0ad2SJack F Vogel { 32048cfa0ad2SJack F Vogel u32 reg; 32058cfa0ad2SJack F Vogel u16 data; 32068cfa0ad2SJack F Vogel u8 retry = 0; 32078cfa0ad2SJack F Vogel 32088cfa0ad2SJack F Vogel DEBUGFUNC("e1000_igp3_phy_powerdown_workaround_ich8lan"); 32098cfa0ad2SJack F Vogel 32108cfa0ad2SJack F Vogel if (hw->phy.type != e1000_phy_igp_3) 32118cfa0ad2SJack F Vogel goto out; 32128cfa0ad2SJack F Vogel 32138cfa0ad2SJack F Vogel /* Try the workaround twice (if needed) */ 32148cfa0ad2SJack F Vogel do { 32158cfa0ad2SJack F Vogel /* Disable link */ 32168cfa0ad2SJack F Vogel reg = E1000_READ_REG(hw, E1000_PHY_CTRL); 32178cfa0ad2SJack F Vogel reg |= (E1000_PHY_CTRL_GBE_DISABLE | 32188cfa0ad2SJack F Vogel E1000_PHY_CTRL_NOND0A_GBE_DISABLE); 32198cfa0ad2SJack F Vogel E1000_WRITE_REG(hw, E1000_PHY_CTRL, reg); 32208cfa0ad2SJack F Vogel 32218cfa0ad2SJack F Vogel /* 32228cfa0ad2SJack F Vogel * Call gig speed drop workaround on Gig disable before 32238cfa0ad2SJack F Vogel * accessing any PHY registers 32248cfa0ad2SJack F Vogel */ 32258cfa0ad2SJack F Vogel if (hw->mac.type == e1000_ich8lan) 32268cfa0ad2SJack F Vogel e1000_gig_downshift_workaround_ich8lan(hw); 32278cfa0ad2SJack F Vogel 32288cfa0ad2SJack F Vogel /* Write VR power-down enable */ 32298cfa0ad2SJack F Vogel hw->phy.ops.read_reg(hw, IGP3_VR_CTRL, &data); 32308cfa0ad2SJack F Vogel data &= ~IGP3_VR_CTRL_DEV_POWERDOWN_MODE_MASK; 3231daf9197cSJack F Vogel hw->phy.ops.write_reg(hw, IGP3_VR_CTRL, 32328cfa0ad2SJack F Vogel data | IGP3_VR_CTRL_MODE_SHUTDOWN); 32338cfa0ad2SJack F Vogel 32348cfa0ad2SJack F Vogel /* Read it back and test */ 32358cfa0ad2SJack F Vogel hw->phy.ops.read_reg(hw, IGP3_VR_CTRL, &data); 32368cfa0ad2SJack F Vogel data &= IGP3_VR_CTRL_DEV_POWERDOWN_MODE_MASK; 32378cfa0ad2SJack F Vogel if ((data == IGP3_VR_CTRL_MODE_SHUTDOWN) || retry) 32388cfa0ad2SJack F Vogel break; 32398cfa0ad2SJack F Vogel 32408cfa0ad2SJack F Vogel /* Issue PHY reset and repeat at most one more time */ 32418cfa0ad2SJack F Vogel reg = E1000_READ_REG(hw, E1000_CTRL); 32428cfa0ad2SJack F Vogel E1000_WRITE_REG(hw, E1000_CTRL, reg | E1000_CTRL_PHY_RST); 32438cfa0ad2SJack F Vogel retry++; 32448cfa0ad2SJack F Vogel } while (retry); 32458cfa0ad2SJack F Vogel 32468cfa0ad2SJack F Vogel out: 32478cfa0ad2SJack F Vogel return; 32488cfa0ad2SJack F Vogel } 32498cfa0ad2SJack F Vogel 32508cfa0ad2SJack F Vogel /** 32518cfa0ad2SJack F Vogel * e1000_gig_downshift_workaround_ich8lan - WoL from S5 stops working 32528cfa0ad2SJack F Vogel * @hw: pointer to the HW structure 32538cfa0ad2SJack F Vogel * 32548cfa0ad2SJack F Vogel * Steps to take when dropping from 1Gb/s (eg. link cable removal (LSC), 32558cfa0ad2SJack F Vogel * LPLU, Gig disable, MDIC PHY reset): 32568cfa0ad2SJack F Vogel * 1) Set Kumeran Near-end loopback 32578cfa0ad2SJack F Vogel * 2) Clear Kumeran Near-end loopback 32588cfa0ad2SJack F Vogel * Should only be called for ICH8[m] devices with IGP_3 Phy. 32598cfa0ad2SJack F Vogel **/ 32608cfa0ad2SJack F Vogel void e1000_gig_downshift_workaround_ich8lan(struct e1000_hw *hw) 32618cfa0ad2SJack F Vogel { 32628cfa0ad2SJack F Vogel s32 ret_val = E1000_SUCCESS; 32638cfa0ad2SJack F Vogel u16 reg_data; 32648cfa0ad2SJack F Vogel 32658cfa0ad2SJack F Vogel DEBUGFUNC("e1000_gig_downshift_workaround_ich8lan"); 32668cfa0ad2SJack F Vogel 32678cfa0ad2SJack F Vogel if ((hw->mac.type != e1000_ich8lan) || 32688cfa0ad2SJack F Vogel (hw->phy.type != e1000_phy_igp_3)) 32698cfa0ad2SJack F Vogel goto out; 32708cfa0ad2SJack F Vogel 32718cfa0ad2SJack F Vogel ret_val = e1000_read_kmrn_reg_generic(hw, E1000_KMRNCTRLSTA_DIAG_OFFSET, 32728cfa0ad2SJack F Vogel ®_data); 32738cfa0ad2SJack F Vogel if (ret_val) 32748cfa0ad2SJack F Vogel goto out; 32758cfa0ad2SJack F Vogel reg_data |= E1000_KMRNCTRLSTA_DIAG_NELPBK; 32768cfa0ad2SJack F Vogel ret_val = e1000_write_kmrn_reg_generic(hw, 32778cfa0ad2SJack F Vogel E1000_KMRNCTRLSTA_DIAG_OFFSET, 32788cfa0ad2SJack F Vogel reg_data); 32798cfa0ad2SJack F Vogel if (ret_val) 32808cfa0ad2SJack F Vogel goto out; 32818cfa0ad2SJack F Vogel reg_data &= ~E1000_KMRNCTRLSTA_DIAG_NELPBK; 32828cfa0ad2SJack F Vogel ret_val = e1000_write_kmrn_reg_generic(hw, 32838cfa0ad2SJack F Vogel E1000_KMRNCTRLSTA_DIAG_OFFSET, 32848cfa0ad2SJack F Vogel reg_data); 32858cfa0ad2SJack F Vogel out: 32868cfa0ad2SJack F Vogel return; 32878cfa0ad2SJack F Vogel } 32888cfa0ad2SJack F Vogel 32898cfa0ad2SJack F Vogel /** 32908cfa0ad2SJack F Vogel * e1000_disable_gig_wol_ich8lan - disable gig during WoL 32918cfa0ad2SJack F Vogel * @hw: pointer to the HW structure 32928cfa0ad2SJack F Vogel * 32938cfa0ad2SJack F Vogel * During S0 to Sx transition, it is possible the link remains at gig 32948cfa0ad2SJack F Vogel * instead of negotiating to a lower speed. Before going to Sx, set 32958cfa0ad2SJack F Vogel * 'LPLU Enabled' and 'Gig Disable' to force link speed negotiation 32968cfa0ad2SJack F Vogel * to a lower speed. 32978cfa0ad2SJack F Vogel * 3298d035aa2dSJack F Vogel * Should only be called for applicable parts. 32998cfa0ad2SJack F Vogel **/ 33008cfa0ad2SJack F Vogel void e1000_disable_gig_wol_ich8lan(struct e1000_hw *hw) 33018cfa0ad2SJack F Vogel { 33028cfa0ad2SJack F Vogel u32 phy_ctrl; 33038cfa0ad2SJack F Vogel 3304d035aa2dSJack F Vogel switch (hw->mac.type) { 33054edd8523SJack F Vogel case e1000_ich8lan: 3306d035aa2dSJack F Vogel case e1000_ich9lan: 3307d035aa2dSJack F Vogel case e1000_ich10lan: 33089d81738fSJack F Vogel case e1000_pchlan: 33098cfa0ad2SJack F Vogel phy_ctrl = E1000_READ_REG(hw, E1000_PHY_CTRL); 33108cfa0ad2SJack F Vogel phy_ctrl |= E1000_PHY_CTRL_D0A_LPLU | 33118cfa0ad2SJack F Vogel E1000_PHY_CTRL_GBE_DISABLE; 33128cfa0ad2SJack F Vogel E1000_WRITE_REG(hw, E1000_PHY_CTRL, phy_ctrl); 33139d81738fSJack F Vogel 33149d81738fSJack F Vogel if (hw->mac.type == e1000_pchlan) 33154edd8523SJack F Vogel e1000_phy_hw_reset_ich8lan(hw); 3316d035aa2dSJack F Vogel default: 3317d035aa2dSJack F Vogel break; 33188cfa0ad2SJack F Vogel } 33198cfa0ad2SJack F Vogel 33208cfa0ad2SJack F Vogel return; 33218cfa0ad2SJack F Vogel } 33228cfa0ad2SJack F Vogel 33238cfa0ad2SJack F Vogel /** 33248cfa0ad2SJack F Vogel * e1000_cleanup_led_ich8lan - Restore the default LED operation 33258cfa0ad2SJack F Vogel * @hw: pointer to the HW structure 33268cfa0ad2SJack F Vogel * 33278cfa0ad2SJack F Vogel * Return the LED back to the default configuration. 33288cfa0ad2SJack F Vogel **/ 33298cfa0ad2SJack F Vogel static s32 e1000_cleanup_led_ich8lan(struct e1000_hw *hw) 33308cfa0ad2SJack F Vogel { 33318cfa0ad2SJack F Vogel DEBUGFUNC("e1000_cleanup_led_ich8lan"); 33328cfa0ad2SJack F Vogel 33338cfa0ad2SJack F Vogel if (hw->phy.type == e1000_phy_ife) 3334a69ed8dfSJack F Vogel return hw->phy.ops.write_reg(hw, IFE_PHY_SPECIAL_CONTROL_LED, 33358cfa0ad2SJack F Vogel 0); 33368cfa0ad2SJack F Vogel 3337a69ed8dfSJack F Vogel E1000_WRITE_REG(hw, E1000_LEDCTL, hw->mac.ledctl_default); 3338a69ed8dfSJack F Vogel return E1000_SUCCESS; 33398cfa0ad2SJack F Vogel } 33408cfa0ad2SJack F Vogel 33418cfa0ad2SJack F Vogel /** 33428cfa0ad2SJack F Vogel * e1000_led_on_ich8lan - Turn LEDs on 33438cfa0ad2SJack F Vogel * @hw: pointer to the HW structure 33448cfa0ad2SJack F Vogel * 33458cfa0ad2SJack F Vogel * Turn on the LEDs. 33468cfa0ad2SJack F Vogel **/ 33478cfa0ad2SJack F Vogel static s32 e1000_led_on_ich8lan(struct e1000_hw *hw) 33488cfa0ad2SJack F Vogel { 33498cfa0ad2SJack F Vogel DEBUGFUNC("e1000_led_on_ich8lan"); 33508cfa0ad2SJack F Vogel 33518cfa0ad2SJack F Vogel if (hw->phy.type == e1000_phy_ife) 3352a69ed8dfSJack F Vogel return hw->phy.ops.write_reg(hw, IFE_PHY_SPECIAL_CONTROL_LED, 33538cfa0ad2SJack F Vogel (IFE_PSCL_PROBE_MODE | IFE_PSCL_PROBE_LEDS_ON)); 33548cfa0ad2SJack F Vogel 3355a69ed8dfSJack F Vogel E1000_WRITE_REG(hw, E1000_LEDCTL, hw->mac.ledctl_mode2); 3356a69ed8dfSJack F Vogel return E1000_SUCCESS; 33578cfa0ad2SJack F Vogel } 33588cfa0ad2SJack F Vogel 33598cfa0ad2SJack F Vogel /** 33608cfa0ad2SJack F Vogel * e1000_led_off_ich8lan - Turn LEDs off 33618cfa0ad2SJack F Vogel * @hw: pointer to the HW structure 33628cfa0ad2SJack F Vogel * 33638cfa0ad2SJack F Vogel * Turn off the LEDs. 33648cfa0ad2SJack F Vogel **/ 33658cfa0ad2SJack F Vogel static s32 e1000_led_off_ich8lan(struct e1000_hw *hw) 33668cfa0ad2SJack F Vogel { 33678cfa0ad2SJack F Vogel DEBUGFUNC("e1000_led_off_ich8lan"); 33688cfa0ad2SJack F Vogel 33698cfa0ad2SJack F Vogel if (hw->phy.type == e1000_phy_ife) 3370a69ed8dfSJack F Vogel return hw->phy.ops.write_reg(hw, IFE_PHY_SPECIAL_CONTROL_LED, 33718cfa0ad2SJack F Vogel (IFE_PSCL_PROBE_MODE | IFE_PSCL_PROBE_LEDS_OFF)); 33728cfa0ad2SJack F Vogel 3373a69ed8dfSJack F Vogel E1000_WRITE_REG(hw, E1000_LEDCTL, hw->mac.ledctl_mode1); 3374a69ed8dfSJack F Vogel return E1000_SUCCESS; 33758cfa0ad2SJack F Vogel } 33768cfa0ad2SJack F Vogel 33778cfa0ad2SJack F Vogel /** 33789d81738fSJack F Vogel * e1000_setup_led_pchlan - Configures SW controllable LED 33799d81738fSJack F Vogel * @hw: pointer to the HW structure 33809d81738fSJack F Vogel * 33819d81738fSJack F Vogel * This prepares the SW controllable LED for use. 33829d81738fSJack F Vogel **/ 33839d81738fSJack F Vogel static s32 e1000_setup_led_pchlan(struct e1000_hw *hw) 33849d81738fSJack F Vogel { 33859d81738fSJack F Vogel DEBUGFUNC("e1000_setup_led_pchlan"); 33869d81738fSJack F Vogel 33879d81738fSJack F Vogel return hw->phy.ops.write_reg(hw, HV_LED_CONFIG, 33889d81738fSJack F Vogel (u16)hw->mac.ledctl_mode1); 33899d81738fSJack F Vogel } 33909d81738fSJack F Vogel 33919d81738fSJack F Vogel /** 33929d81738fSJack F Vogel * e1000_cleanup_led_pchlan - Restore the default LED operation 33939d81738fSJack F Vogel * @hw: pointer to the HW structure 33949d81738fSJack F Vogel * 33959d81738fSJack F Vogel * Return the LED back to the default configuration. 33969d81738fSJack F Vogel **/ 33979d81738fSJack F Vogel static s32 e1000_cleanup_led_pchlan(struct e1000_hw *hw) 33989d81738fSJack F Vogel { 33999d81738fSJack F Vogel DEBUGFUNC("e1000_cleanup_led_pchlan"); 34009d81738fSJack F Vogel 34019d81738fSJack F Vogel return hw->phy.ops.write_reg(hw, HV_LED_CONFIG, 34029d81738fSJack F Vogel (u16)hw->mac.ledctl_default); 34039d81738fSJack F Vogel } 34049d81738fSJack F Vogel 34059d81738fSJack F Vogel /** 34069d81738fSJack F Vogel * e1000_led_on_pchlan - Turn LEDs on 34079d81738fSJack F Vogel * @hw: pointer to the HW structure 34089d81738fSJack F Vogel * 34099d81738fSJack F Vogel * Turn on the LEDs. 34109d81738fSJack F Vogel **/ 34119d81738fSJack F Vogel static s32 e1000_led_on_pchlan(struct e1000_hw *hw) 34129d81738fSJack F Vogel { 34139d81738fSJack F Vogel u16 data = (u16)hw->mac.ledctl_mode2; 34149d81738fSJack F Vogel u32 i, led; 34159d81738fSJack F Vogel 34169d81738fSJack F Vogel DEBUGFUNC("e1000_led_on_pchlan"); 34179d81738fSJack F Vogel 34189d81738fSJack F Vogel /* 34199d81738fSJack F Vogel * If no link, then turn LED on by setting the invert bit 34209d81738fSJack F Vogel * for each LED that's mode is "link_up" in ledctl_mode2. 34219d81738fSJack F Vogel */ 34229d81738fSJack F Vogel if (!(E1000_READ_REG(hw, E1000_STATUS) & E1000_STATUS_LU)) { 34239d81738fSJack F Vogel for (i = 0; i < 3; i++) { 34249d81738fSJack F Vogel led = (data >> (i * 5)) & E1000_PHY_LED0_MASK; 34259d81738fSJack F Vogel if ((led & E1000_PHY_LED0_MODE_MASK) != 34269d81738fSJack F Vogel E1000_LEDCTL_MODE_LINK_UP) 34279d81738fSJack F Vogel continue; 34289d81738fSJack F Vogel if (led & E1000_PHY_LED0_IVRT) 34299d81738fSJack F Vogel data &= ~(E1000_PHY_LED0_IVRT << (i * 5)); 34309d81738fSJack F Vogel else 34319d81738fSJack F Vogel data |= (E1000_PHY_LED0_IVRT << (i * 5)); 34329d81738fSJack F Vogel } 34339d81738fSJack F Vogel } 34349d81738fSJack F Vogel 34359d81738fSJack F Vogel return hw->phy.ops.write_reg(hw, HV_LED_CONFIG, data); 34369d81738fSJack F Vogel } 34379d81738fSJack F Vogel 34389d81738fSJack F Vogel /** 34399d81738fSJack F Vogel * e1000_led_off_pchlan - Turn LEDs off 34409d81738fSJack F Vogel * @hw: pointer to the HW structure 34419d81738fSJack F Vogel * 34429d81738fSJack F Vogel * Turn off the LEDs. 34439d81738fSJack F Vogel **/ 34449d81738fSJack F Vogel static s32 e1000_led_off_pchlan(struct e1000_hw *hw) 34459d81738fSJack F Vogel { 34469d81738fSJack F Vogel u16 data = (u16)hw->mac.ledctl_mode1; 34479d81738fSJack F Vogel u32 i, led; 34489d81738fSJack F Vogel 34499d81738fSJack F Vogel DEBUGFUNC("e1000_led_off_pchlan"); 34509d81738fSJack F Vogel 34519d81738fSJack F Vogel /* 34529d81738fSJack F Vogel * If no link, then turn LED off by clearing the invert bit 34539d81738fSJack F Vogel * for each LED that's mode is "link_up" in ledctl_mode1. 34549d81738fSJack F Vogel */ 34559d81738fSJack F Vogel if (!(E1000_READ_REG(hw, E1000_STATUS) & E1000_STATUS_LU)) { 34569d81738fSJack F Vogel for (i = 0; i < 3; i++) { 34579d81738fSJack F Vogel led = (data >> (i * 5)) & E1000_PHY_LED0_MASK; 34589d81738fSJack F Vogel if ((led & E1000_PHY_LED0_MODE_MASK) != 34599d81738fSJack F Vogel E1000_LEDCTL_MODE_LINK_UP) 34609d81738fSJack F Vogel continue; 34619d81738fSJack F Vogel if (led & E1000_PHY_LED0_IVRT) 34629d81738fSJack F Vogel data &= ~(E1000_PHY_LED0_IVRT << (i * 5)); 34639d81738fSJack F Vogel else 34649d81738fSJack F Vogel data |= (E1000_PHY_LED0_IVRT << (i * 5)); 34659d81738fSJack F Vogel } 34669d81738fSJack F Vogel } 34679d81738fSJack F Vogel 34689d81738fSJack F Vogel return hw->phy.ops.write_reg(hw, HV_LED_CONFIG, data); 34699d81738fSJack F Vogel } 34709d81738fSJack F Vogel 34719d81738fSJack F Vogel /** 34728cfa0ad2SJack F Vogel * e1000_get_cfg_done_ich8lan - Read config done bit 34738cfa0ad2SJack F Vogel * @hw: pointer to the HW structure 34748cfa0ad2SJack F Vogel * 34758cfa0ad2SJack F Vogel * Read the management control register for the config done bit for 34768cfa0ad2SJack F Vogel * completion status. NOTE: silicon which is EEPROM-less will fail trying 34778cfa0ad2SJack F Vogel * to read the config done bit, so an error is *ONLY* logged and returns 34788cfa0ad2SJack F Vogel * E1000_SUCCESS. If we were to return with error, EEPROM-less silicon 34798cfa0ad2SJack F Vogel * would not be able to be reset or change link. 34808cfa0ad2SJack F Vogel **/ 34818cfa0ad2SJack F Vogel static s32 e1000_get_cfg_done_ich8lan(struct e1000_hw *hw) 34828cfa0ad2SJack F Vogel { 34838cfa0ad2SJack F Vogel s32 ret_val = E1000_SUCCESS; 34848cfa0ad2SJack F Vogel u32 bank = 0; 34858cfa0ad2SJack F Vogel 34869d81738fSJack F Vogel if (hw->mac.type >= e1000_pchlan) { 34879d81738fSJack F Vogel u32 status = E1000_READ_REG(hw, E1000_STATUS); 34889d81738fSJack F Vogel 34894edd8523SJack F Vogel if (status & E1000_STATUS_PHYRA) 34909d81738fSJack F Vogel E1000_WRITE_REG(hw, E1000_STATUS, status & 34919d81738fSJack F Vogel ~E1000_STATUS_PHYRA); 34924edd8523SJack F Vogel else 34939d81738fSJack F Vogel DEBUGOUT("PHY Reset Asserted not set - needs delay\n"); 34949d81738fSJack F Vogel } 34959d81738fSJack F Vogel 34968cfa0ad2SJack F Vogel e1000_get_cfg_done_generic(hw); 34978cfa0ad2SJack F Vogel 34988cfa0ad2SJack F Vogel /* If EEPROM is not marked present, init the IGP 3 PHY manually */ 34994edd8523SJack F Vogel if (hw->mac.type <= e1000_ich9lan) { 35008cfa0ad2SJack F Vogel if (((E1000_READ_REG(hw, E1000_EECD) & E1000_EECD_PRES) == 0) && 35018cfa0ad2SJack F Vogel (hw->phy.type == e1000_phy_igp_3)) { 35028cfa0ad2SJack F Vogel e1000_phy_init_script_igp3(hw); 35038cfa0ad2SJack F Vogel } 35048cfa0ad2SJack F Vogel } else { 35058cfa0ad2SJack F Vogel if (e1000_valid_nvm_bank_detect_ich8lan(hw, &bank)) { 3506daf9197cSJack F Vogel /* Maybe we should do a basic PHY config */ 35078cfa0ad2SJack F Vogel DEBUGOUT("EEPROM not present\n"); 35088cfa0ad2SJack F Vogel ret_val = -E1000_ERR_CONFIG; 35098cfa0ad2SJack F Vogel } 35108cfa0ad2SJack F Vogel } 35118cfa0ad2SJack F Vogel 35128cfa0ad2SJack F Vogel return ret_val; 35138cfa0ad2SJack F Vogel } 35148cfa0ad2SJack F Vogel 35158cfa0ad2SJack F Vogel /** 35168cfa0ad2SJack F Vogel * e1000_power_down_phy_copper_ich8lan - Remove link during PHY power down 35178cfa0ad2SJack F Vogel * @hw: pointer to the HW structure 35188cfa0ad2SJack F Vogel * 35198cfa0ad2SJack F Vogel * In the case of a PHY power down to save power, or to turn off link during a 35208cfa0ad2SJack F Vogel * driver unload, or wake on lan is not enabled, remove the link. 35218cfa0ad2SJack F Vogel **/ 35228cfa0ad2SJack F Vogel static void e1000_power_down_phy_copper_ich8lan(struct e1000_hw *hw) 35238cfa0ad2SJack F Vogel { 35248cfa0ad2SJack F Vogel /* If the management interface is not enabled, then power down */ 3525daf9197cSJack F Vogel if (!(hw->mac.ops.check_mng_mode(hw) || 3526daf9197cSJack F Vogel hw->phy.ops.check_reset_block(hw))) 35278cfa0ad2SJack F Vogel e1000_power_down_phy_copper(hw); 35288cfa0ad2SJack F Vogel 35298cfa0ad2SJack F Vogel return; 35308cfa0ad2SJack F Vogel } 35318cfa0ad2SJack F Vogel 35328cfa0ad2SJack F Vogel /** 35338cfa0ad2SJack F Vogel * e1000_clear_hw_cntrs_ich8lan - Clear statistical counters 35348cfa0ad2SJack F Vogel * @hw: pointer to the HW structure 35358cfa0ad2SJack F Vogel * 35368cfa0ad2SJack F Vogel * Clears hardware counters specific to the silicon family and calls 35378cfa0ad2SJack F Vogel * clear_hw_cntrs_generic to clear all general purpose counters. 35388cfa0ad2SJack F Vogel **/ 35398cfa0ad2SJack F Vogel static void e1000_clear_hw_cntrs_ich8lan(struct e1000_hw *hw) 35408cfa0ad2SJack F Vogel { 35419d81738fSJack F Vogel u16 phy_data; 35429d81738fSJack F Vogel 35438cfa0ad2SJack F Vogel DEBUGFUNC("e1000_clear_hw_cntrs_ich8lan"); 35448cfa0ad2SJack F Vogel 35458cfa0ad2SJack F Vogel e1000_clear_hw_cntrs_base_generic(hw); 35468cfa0ad2SJack F Vogel 3547daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_ALGNERRC); 3548daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_RXERRC); 3549daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_TNCRS); 3550daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_CEXTERR); 3551daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_TSCTC); 3552daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_TSCTFC); 35538cfa0ad2SJack F Vogel 3554daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_MGTPRC); 3555daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_MGTPDC); 3556daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_MGTPTC); 35578cfa0ad2SJack F Vogel 3558daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_IAC); 3559daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_ICRXOC); 35609d81738fSJack F Vogel 35619d81738fSJack F Vogel /* Clear PHY statistics registers */ 35629d81738fSJack F Vogel if ((hw->phy.type == e1000_phy_82578) || 35639d81738fSJack F Vogel (hw->phy.type == e1000_phy_82577)) { 35649d81738fSJack F Vogel hw->phy.ops.read_reg(hw, HV_SCC_UPPER, &phy_data); 35659d81738fSJack F Vogel hw->phy.ops.read_reg(hw, HV_SCC_LOWER, &phy_data); 35669d81738fSJack F Vogel hw->phy.ops.read_reg(hw, HV_ECOL_UPPER, &phy_data); 35679d81738fSJack F Vogel hw->phy.ops.read_reg(hw, HV_ECOL_LOWER, &phy_data); 35689d81738fSJack F Vogel hw->phy.ops.read_reg(hw, HV_MCC_UPPER, &phy_data); 35699d81738fSJack F Vogel hw->phy.ops.read_reg(hw, HV_MCC_LOWER, &phy_data); 35709d81738fSJack F Vogel hw->phy.ops.read_reg(hw, HV_LATECOL_UPPER, &phy_data); 35719d81738fSJack F Vogel hw->phy.ops.read_reg(hw, HV_LATECOL_LOWER, &phy_data); 35729d81738fSJack F Vogel hw->phy.ops.read_reg(hw, HV_COLC_UPPER, &phy_data); 35739d81738fSJack F Vogel hw->phy.ops.read_reg(hw, HV_COLC_LOWER, &phy_data); 35749d81738fSJack F Vogel hw->phy.ops.read_reg(hw, HV_DC_UPPER, &phy_data); 35759d81738fSJack F Vogel hw->phy.ops.read_reg(hw, HV_DC_LOWER, &phy_data); 35769d81738fSJack F Vogel hw->phy.ops.read_reg(hw, HV_TNCRS_UPPER, &phy_data); 35779d81738fSJack F Vogel hw->phy.ops.read_reg(hw, HV_TNCRS_LOWER, &phy_data); 35789d81738fSJack F Vogel } 35798cfa0ad2SJack F Vogel } 35808cfa0ad2SJack F Vogel 3581