75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi/******************************************************************************
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
49b7860084dbba18bc00b29413d6182197f9fe93Robert Mustacchi Copyright (c) 2001-2015, Intel Corporation
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi All rights reserved.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi Redistribution and use in source and binary forms, with or without
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi modification, are permitted provided that the following conditions are met:
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi 1. Redistributions of source code must retain the above copyright notice,
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi this list of conditions and the following disclaimer.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi 2. Redistributions in binary form must reproduce the above copyright
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi notice, this list of conditions and the following disclaimer in the
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi documentation and/or other materials provided with the distribution.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi 3. Neither the name of the Intel Corporation nor the names of its
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi contributors may be used to endorse or promote products derived from
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi this software without specific prior written permission.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi POSSIBILITY OF SUCH DAMAGE.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi******************************************************************************/
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi/*$FreeBSD$*/
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi#include "e1000_api.h"
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchistatic s32 e1000_wait_autoneg(struct e1000_hw *hw);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchistatic s32 e1000_access_phy_wakeup_reg_bm(struct e1000_hw *hw, u32 offset,
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi u16 *data, bool read, bool page_set);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchistatic u32 e1000_get_phy_addr_for_hv_page(u32 page);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchistatic s32 e1000_access_phy_debug_regs_hv(struct e1000_hw *hw, u32 offset,
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi u16 *data, bool read);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi/* Cable length tables */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchistatic const u16 e1000_m88_cable_length_table[] = {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi 0, 50, 80, 110, 140, 140, E1000_CABLE_LENGTH_UNDEFINED };
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi#define M88E1000_CABLE_LENGTH_TABLE_SIZE \
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi (sizeof(e1000_m88_cable_length_table) / \
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi sizeof(e1000_m88_cable_length_table[0]))
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchistatic const u16 e1000_igp_2_cable_length_table[] = {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi 0, 0, 0, 0, 0, 0, 0, 0, 3, 5, 8, 11, 13, 16, 18, 21, 0, 0, 0, 3,
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi 6, 10, 13, 16, 19, 23, 26, 29, 32, 35, 38, 41, 6, 10, 14, 18, 22,
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi 26, 30, 33, 37, 41, 44, 48, 51, 54, 58, 61, 21, 26, 31, 35, 40,
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi 44, 49, 53, 57, 61, 65, 68, 72, 75, 79, 82, 40, 45, 51, 56, 61,
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi 66, 70, 75, 79, 83, 87, 91, 94, 98, 101, 104, 60, 66, 72, 77, 82,
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi 87, 92, 96, 100, 104, 108, 111, 114, 117, 119, 121, 83, 89, 95,
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi 100, 105, 109, 113, 116, 119, 122, 124, 104, 109, 114, 118, 121,
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi 124};
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi#define IGP02E1000_CABLE_LENGTH_TABLE_SIZE \
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi (sizeof(e1000_igp_2_cable_length_table) / \
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi sizeof(e1000_igp_2_cable_length_table[0]))
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi/**
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * e1000_init_phy_ops_generic - Initialize PHY function pointers
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @hw: pointer to the HW structure
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi *
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * Setups up the function pointers to no-op functions
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi **/
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchivoid e1000_init_phy_ops_generic(struct e1000_hw *hw)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi{
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi struct e1000_phy_info *phy = &hw->phy;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGFUNC("e1000_init_phy_ops_generic");
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* Initialize function pointers */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi phy->ops.init_params = e1000_null_ops_generic;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi phy->ops.acquire = e1000_null_ops_generic;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi phy->ops.check_polarity = e1000_null_ops_generic;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi phy->ops.check_reset_block = e1000_null_ops_generic;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi phy->ops.commit = e1000_null_ops_generic;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi phy->ops.force_speed_duplex = e1000_null_ops_generic;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi phy->ops.get_cfg_done = e1000_null_ops_generic;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi phy->ops.get_cable_length = e1000_null_ops_generic;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi phy->ops.get_info = e1000_null_ops_generic;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi phy->ops.set_page = e1000_null_set_page;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi phy->ops.read_reg = e1000_null_read_reg;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi phy->ops.read_reg_locked = e1000_null_read_reg;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi phy->ops.read_reg_page = e1000_null_read_reg;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi phy->ops.release = e1000_null_phy_generic;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi phy->ops.reset = e1000_null_ops_generic;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi phy->ops.set_d0_lplu_state = e1000_null_lplu_state;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi phy->ops.set_d3_lplu_state = e1000_null_lplu_state;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi phy->ops.write_reg = e1000_null_write_reg;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi phy->ops.write_reg_locked = e1000_null_write_reg;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi phy->ops.write_reg_page = e1000_null_write_reg;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi phy->ops.power_up = e1000_null_phy_generic;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi phy->ops.power_down = e1000_null_phy_generic;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi phy->ops.read_i2c_byte = e1000_read_i2c_byte_null;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi phy->ops.write_i2c_byte = e1000_write_i2c_byte_null;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi phy->ops.cfg_on_link_up = e1000_null_ops_generic;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi}
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi/**
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * e1000_null_set_page - No-op function, return 0
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @hw: pointer to the HW structure
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi **/
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchis32 e1000_null_set_page(struct e1000_hw E1000_UNUSEDARG *hw,
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi u16 E1000_UNUSEDARG data)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi{
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGFUNC("e1000_null_set_page");
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return E1000_SUCCESS;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi}
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi/**
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * e1000_null_read_reg - No-op function, return 0
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @hw: pointer to the HW structure
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi **/
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchis32 e1000_null_read_reg(struct e1000_hw E1000_UNUSEDARG *hw,
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi u32 E1000_UNUSEDARG offset, u16 E1000_UNUSEDARG *data)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi{
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGFUNC("e1000_null_read_reg");
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return E1000_SUCCESS;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi}
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi/**
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * e1000_null_phy_generic - No-op function, return void
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @hw: pointer to the HW structure
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi **/
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchivoid e1000_null_phy_generic(struct e1000_hw E1000_UNUSEDARG *hw)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi{
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGFUNC("e1000_null_phy_generic");
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi}
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi/**
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * e1000_null_lplu_state - No-op function, return 0
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @hw: pointer to the HW structure
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi **/
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchis32 e1000_null_lplu_state(struct e1000_hw E1000_UNUSEDARG *hw,
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi bool E1000_UNUSEDARG active)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi{
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGFUNC("e1000_null_lplu_state");
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return E1000_SUCCESS;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi}
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi/**
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * e1000_null_write_reg - No-op function, return 0
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @hw: pointer to the HW structure
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi **/
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchis32 e1000_null_write_reg(struct e1000_hw E1000_UNUSEDARG *hw,
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi u32 E1000_UNUSEDARG offset, u16 E1000_UNUSEDARG data)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi{
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGFUNC("e1000_null_write_reg");
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return E1000_SUCCESS;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi}
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi/**
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * e1000_read_i2c_byte_null - No-op function, return 0
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @hw: pointer to hardware structure
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @byte_offset: byte offset to write
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @dev_addr: device address
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @data: data value read
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi *
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi **/
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchis32 e1000_read_i2c_byte_null(struct e1000_hw E1000_UNUSEDARG *hw,
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi u8 E1000_UNUSEDARG byte_offset,
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi u8 E1000_UNUSEDARG dev_addr,
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi u8 E1000_UNUSEDARG *data)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi{
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGFUNC("e1000_read_i2c_byte_null");
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return E1000_SUCCESS;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi}
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi/**
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * e1000_write_i2c_byte_null - No-op function, return 0
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @hw: pointer to hardware structure
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @byte_offset: byte offset to write
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @dev_addr: device address
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @data: data value to write
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi *
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi **/
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchis32 e1000_write_i2c_byte_null(struct e1000_hw E1000_UNUSEDARG *hw,
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi u8 E1000_UNUSEDARG byte_offset,
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi u8 E1000_UNUSEDARG dev_addr,
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi u8 E1000_UNUSEDARG data)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi{
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGFUNC("e1000_write_i2c_byte_null");
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return E1000_SUCCESS;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi}
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi/**
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * e1000_check_reset_block_generic - Check if PHY reset is blocked
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @hw: pointer to the HW structure
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi *
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * Read the PHY management control register and check whether a PHY reset
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * is blocked. If a reset is not blocked return E1000_SUCCESS, otherwise
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * return E1000_BLK_PHY_RESET (12).
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi **/
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchis32 e1000_check_reset_block_generic(struct e1000_hw *hw)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi{
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi u32 manc;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGFUNC("e1000_check_reset_block");
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi manc = E1000_READ_REG(hw, E1000_MANC);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return (manc & E1000_MANC_BLK_PHY_RST_ON_IDE) ?
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi E1000_BLK_PHY_RESET : E1000_SUCCESS;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi}
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi/**
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * e1000_get_phy_id - Retrieve the PHY ID and revision
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @hw: pointer to the HW structure
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi *
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * Reads the PHY registers and stores the PHY ID and possibly the PHY
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * revision in the hardware structure.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi **/
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchis32 e1000_get_phy_id(struct e1000_hw *hw)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi{
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi struct e1000_phy_info *phy = &hw->phy;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi s32 ret_val = E1000_SUCCESS;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi u16 phy_id;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi u16 retry_count = 0;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGFUNC("e1000_get_phy_id");
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (!phy->ops.read_reg)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return E1000_SUCCESS;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi while (retry_count < 2) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = phy->ops.read_reg(hw, PHY_ID1, &phy_id);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (ret_val)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi phy->id = (u32)(phy_id << 16);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi usec_delay(20);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = phy->ops.read_reg(hw, PHY_ID2, &phy_id);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (ret_val)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi phy->id |= (u32)(phy_id & PHY_REVISION_MASK);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi phy->revision = (u32)(phy_id & ~PHY_REVISION_MASK);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (phy->id != 0 && phy->id != PHY_REVISION_MASK)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return E1000_SUCCESS;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi retry_count++;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return E1000_SUCCESS;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi}
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi/**
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * e1000_phy_reset_dsp_generic - Reset PHY DSP
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @hw: pointer to the HW structure
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi *
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * Reset the digital signal processor.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi **/
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchis32 e1000_phy_reset_dsp_generic(struct e1000_hw *hw)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi{
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi s32 ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGFUNC("e1000_phy_reset_dsp_generic");
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (!hw->phy.ops.write_reg)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return E1000_SUCCESS;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = hw->phy.ops.write_reg(hw, M88E1000_PHY_GEN_CONTROL, 0xC1);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (ret_val)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return hw->phy.ops.write_reg(hw, M88E1000_PHY_GEN_CONTROL, 0);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi}
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi/**
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * e1000_read_phy_reg_mdic - Read MDI control register
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @hw: pointer to the HW structure
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @offset: register offset to be read
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @data: pointer to the read data
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi *
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * Reads the MDI control register in the PHY at offset and stores the
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * information read to data.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi **/
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchis32 e1000_read_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 *data)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi{
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi struct e1000_phy_info *phy = &hw->phy;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi u32 i, mdic = 0;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGFUNC("e1000_read_phy_reg_mdic");
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (offset > MAX_PHY_REG_ADDRESS) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGOUT1("PHY Address %d is out of range\n", offset);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return -E1000_ERR_PARAM;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* Set up Op-code, Phy Address, and register offset in the MDI
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * Control register. The MAC will take care of interfacing with the
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * PHY to retrieve the desired data.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi mdic = ((offset << E1000_MDIC_REG_SHIFT) |
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi (phy->addr << E1000_MDIC_PHY_SHIFT) |
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi (E1000_MDIC_OP_READ));
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi E1000_WRITE_REG(hw, E1000_MDIC, mdic);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* Poll the ready bit to see if the MDI read completed
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * Increasing the time out as testing showed failures with
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * the lower time out
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi for (i = 0; i < (E1000_GEN_POLL_TIMEOUT * 3); i++) {
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi usec_delay_irq(50);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi mdic = E1000_READ_REG(hw, E1000_MDIC);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (mdic & E1000_MDIC_READY)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi break;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (!(mdic & E1000_MDIC_READY)) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGOUT("MDI Read did not complete\n");
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return -E1000_ERR_PHY;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (mdic & E1000_MDIC_ERROR) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGOUT("MDI Error\n");
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return -E1000_ERR_PHY;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (((mdic & E1000_MDIC_REG_MASK) >> E1000_MDIC_REG_SHIFT) != offset) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGOUT2("MDI Read offset error - requested %d, returned %d\n",
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi offset,
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi (mdic & E1000_MDIC_REG_MASK) >> E1000_MDIC_REG_SHIFT);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return -E1000_ERR_PHY;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi *data = (u16) mdic;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* Allow some time after each MDIC transaction to avoid
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * reading duplicate data in the next MDIC transaction.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (hw->mac.type == e1000_pch2lan)
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi usec_delay_irq(100);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return E1000_SUCCESS;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi}
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi/**
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * e1000_write_phy_reg_mdic - Write MDI control register
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @hw: pointer to the HW structure
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @offset: register offset to write to
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @data: data to write to register at offset
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi *
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * Writes data to MDI control register in the PHY at offset.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi **/
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchis32 e1000_write_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 data)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi{
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi struct e1000_phy_info *phy = &hw->phy;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi u32 i, mdic = 0;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGFUNC("e1000_write_phy_reg_mdic");
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (offset > MAX_PHY_REG_ADDRESS) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGOUT1("PHY Address %d is out of range\n", offset);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return -E1000_ERR_PARAM;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* Set up Op-code, Phy Address, and register offset in the MDI
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * Control register. The MAC will take care of interfacing with the
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * PHY to retrieve the desired data.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi mdic = (((u32)data) |
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi (offset << E1000_MDIC_REG_SHIFT) |
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi (phy->addr << E1000_MDIC_PHY_SHIFT) |
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi (E1000_MDIC_OP_WRITE));
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi E1000_WRITE_REG(hw, E1000_MDIC, mdic);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* Poll the ready bit to see if the MDI read completed
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * Increasing the time out as testing showed failures with
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * the lower time out
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi for (i = 0; i < (E1000_GEN_POLL_TIMEOUT * 3); i++) {
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi usec_delay_irq(50);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi mdic = E1000_READ_REG(hw, E1000_MDIC);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (mdic & E1000_MDIC_READY)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi break;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (!(mdic & E1000_MDIC_READY)) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGOUT("MDI Write did not complete\n");
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return -E1000_ERR_PHY;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (mdic & E1000_MDIC_ERROR) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGOUT("MDI Error\n");
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return -E1000_ERR_PHY;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (((mdic & E1000_MDIC_REG_MASK) >> E1000_MDIC_REG_SHIFT) != offset) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGOUT2("MDI Write offset error - requested %d, returned %d\n",
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi offset,
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi (mdic & E1000_MDIC_REG_MASK) >> E1000_MDIC_REG_SHIFT);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return -E1000_ERR_PHY;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* Allow some time after each MDIC transaction to avoid
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * reading duplicate data in the next MDIC transaction.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (hw->mac.type == e1000_pch2lan)
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi usec_delay_irq(100);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return E1000_SUCCESS;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi}
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi/**
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * e1000_read_phy_reg_i2c - Read PHY register using i2c
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @hw: pointer to the HW structure
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @offset: register offset to be read
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @data: pointer to the read data
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi *
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * Reads the PHY register at offset using the i2c interface and stores the
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * retrieved information in data.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi **/
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchis32 e1000_read_phy_reg_i2c(struct e1000_hw *hw, u32 offset, u16 *data)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi{
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi struct e1000_phy_info *phy = &hw->phy;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi u32 i, i2ccmd = 0;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGFUNC("e1000_read_phy_reg_i2c");
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* Set up Op-code, Phy Address, and register address in the I2CCMD
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * register. The MAC will take care of interfacing with the
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * PHY to retrieve the desired data.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi i2ccmd = ((offset << E1000_I2CCMD_REG_ADDR_SHIFT) |
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi (phy->addr << E1000_I2CCMD_PHY_ADDR_SHIFT) |
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi (E1000_I2CCMD_OPCODE_READ));
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi E1000_WRITE_REG(hw, E1000_I2CCMD, i2ccmd);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* Poll the ready bit to see if the I2C read completed */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi for (i = 0; i < E1000_I2CCMD_PHY_TIMEOUT; i++) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi usec_delay(50);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi i2ccmd = E1000_READ_REG(hw, E1000_I2CCMD);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (i2ccmd & E1000_I2CCMD_READY)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi break;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (!(i2ccmd & E1000_I2CCMD_READY)) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGOUT("I2CCMD Read did not complete\n");
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return -E1000_ERR_PHY;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (i2ccmd & E1000_I2CCMD_ERROR) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGOUT("I2CCMD Error bit set\n");
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return -E1000_ERR_PHY;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* Need to byte-swap the 16-bit value. */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi *data = ((i2ccmd >> 8) & 0x00FF) | ((i2ccmd << 8) & 0xFF00);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return E1000_SUCCESS;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi}
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi/**
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * e1000_write_phy_reg_i2c - Write PHY register using i2c
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @hw: pointer to the HW structure
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @offset: register offset to write to
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @data: data to write at register offset
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi *
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * Writes the data to PHY register at the offset using the i2c interface.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi **/
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchis32 e1000_write_phy_reg_i2c(struct e1000_hw *hw, u32 offset, u16 data)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi{
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi struct e1000_phy_info *phy = &hw->phy;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi u32 i, i2ccmd = 0;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi u16 phy_data_swapped;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGFUNC("e1000_write_phy_reg_i2c");
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* Prevent overwritting SFP I2C EEPROM which is at A0 address.*/
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if ((hw->phy.addr == 0) || (hw->phy.addr > 7)) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGOUT1("PHY I2C Address %d is out of range.\n",
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi hw->phy.addr);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return -E1000_ERR_CONFIG;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* Swap the data bytes for the I2C interface */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi phy_data_swapped = ((data >> 8) & 0x00FF) | ((data << 8) & 0xFF00);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* Set up Op-code, Phy Address, and register address in the I2CCMD
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * register. The MAC will take care of interfacing with the
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * PHY to retrieve the desired data.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi i2ccmd = ((offset << E1000_I2CCMD_REG_ADDR_SHIFT) |
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi (phy->addr << E1000_I2CCMD_PHY_ADDR_SHIFT) |
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi E1000_I2CCMD_OPCODE_WRITE |
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi phy_data_swapped);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi E1000_WRITE_REG(hw, E1000_I2CCMD, i2ccmd);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* Poll the ready bit to see if the I2C read completed */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi for (i = 0; i < E1000_I2CCMD_PHY_TIMEOUT; i++) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi usec_delay(50);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi i2ccmd = E1000_READ_REG(hw, E1000_I2CCMD);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (i2ccmd & E1000_I2CCMD_READY)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi break;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (!(i2ccmd & E1000_I2CCMD_READY)) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGOUT("I2CCMD Write did not complete\n");
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return -E1000_ERR_PHY;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (i2ccmd & E1000_I2CCMD_ERROR) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGOUT("I2CCMD Error bit set\n");
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return -E1000_ERR_PHY;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return E1000_SUCCESS;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi}
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi/**
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * e1000_read_sfp_data_byte - Reads SFP module data.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @hw: pointer to the HW structure
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @offset: byte location offset to be read
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @data: read data buffer pointer
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi *
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * Reads one byte from SFP module data stored
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * in SFP resided EEPROM memory or SFP diagnostic area.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * Function should be called with
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * E1000_I2CCMD_SFP_DATA_ADDR(<byte offset>) for SFP module database access
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * E1000_I2CCMD_SFP_DIAG_ADDR(<byte offset>) for SFP diagnostics parameters
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * access
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi **/
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchis32 e1000_read_sfp_data_byte(struct e1000_hw *hw, u16 offset, u8 *data)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi{
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi u32 i = 0;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi u32 i2ccmd = 0;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi u32 data_local = 0;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGFUNC("e1000_read_sfp_data_byte");
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (offset > E1000_I2CCMD_SFP_DIAG_ADDR(255)) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGOUT("I2CCMD command address exceeds upper limit\n");
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return -E1000_ERR_PHY;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* Set up Op-code, EEPROM Address,in the I2CCMD
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * register. The MAC will take care of interfacing with the
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * EEPROM to retrieve the desired data.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi i2ccmd = ((offset << E1000_I2CCMD_REG_ADDR_SHIFT) |
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi E1000_I2CCMD_OPCODE_READ);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi E1000_WRITE_REG(hw, E1000_I2CCMD, i2ccmd);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* Poll the ready bit to see if the I2C read completed */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi for (i = 0; i < E1000_I2CCMD_PHY_TIMEOUT; i++) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi usec_delay(50);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi data_local = E1000_READ_REG(hw, E1000_I2CCMD);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (data_local & E1000_I2CCMD_READY)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi break;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (!(data_local & E1000_I2CCMD_READY)) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGOUT("I2CCMD Read did not complete\n");
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return -E1000_ERR_PHY;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (data_local & E1000_I2CCMD_ERROR) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGOUT("I2CCMD Error bit set\n");
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return -E1000_ERR_PHY;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi *data = (u8) data_local & 0xFF;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return E1000_SUCCESS;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi}
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi/**
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * e1000_write_sfp_data_byte - Writes SFP module data.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @hw: pointer to the HW structure
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @offset: byte location offset to write to
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @data: data to write
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi *
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * Writes one byte to SFP module data stored
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * in SFP resided EEPROM memory or SFP diagnostic area.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * Function should be called with
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * E1000_I2CCMD_SFP_DATA_ADDR(<byte offset>) for SFP module database access
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * E1000_I2CCMD_SFP_DIAG_ADDR(<byte offset>) for SFP diagnostics parameters
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * access
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi **/
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchis32 e1000_write_sfp_data_byte(struct e1000_hw *hw, u16 offset, u8 data)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi{
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi u32 i = 0;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi u32 i2ccmd = 0;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi u32 data_local = 0;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGFUNC("e1000_write_sfp_data_byte");
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (offset > E1000_I2CCMD_SFP_DIAG_ADDR(255)) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGOUT("I2CCMD command address exceeds upper limit\n");
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return -E1000_ERR_PHY;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* The programming interface is 16 bits wide
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * so we need to read the whole word first
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * then update appropriate byte lane and write
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * the updated word back.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* Set up Op-code, EEPROM Address,in the I2CCMD
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * register. The MAC will take care of interfacing
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * with an EEPROM to write the data given.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi i2ccmd = ((offset << E1000_I2CCMD_REG_ADDR_SHIFT) |
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi E1000_I2CCMD_OPCODE_READ);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* Set a command to read single word */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi E1000_WRITE_REG(hw, E1000_I2CCMD, i2ccmd);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi for (i = 0; i < E1000_I2CCMD_PHY_TIMEOUT; i++) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi usec_delay(50);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* Poll the ready bit to see if lastly
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * launched I2C operation completed
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi i2ccmd = E1000_READ_REG(hw, E1000_I2CCMD);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (i2ccmd & E1000_I2CCMD_READY) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* Check if this is READ or WRITE phase */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if ((i2ccmd & E1000_I2CCMD_OPCODE_READ) ==
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi E1000_I2CCMD_OPCODE_READ) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* Write the selected byte
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * lane and update whole word
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi data_local = i2ccmd & 0xFF00;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi data_local |= data;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi i2ccmd = ((offset <<
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi E1000_I2CCMD_REG_ADDR_SHIFT) |
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi E1000_I2CCMD_OPCODE_WRITE | data_local);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi E1000_WRITE_REG(hw, E1000_I2CCMD, i2ccmd);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi } else {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi break;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (!(i2ccmd & E1000_I2CCMD_READY)) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGOUT("I2CCMD Write did not complete\n");
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return -E1000_ERR_PHY;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (i2ccmd & E1000_I2CCMD_ERROR) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGOUT("I2CCMD Error bit set\n");
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return -E1000_ERR_PHY;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return E1000_SUCCESS;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi}
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi/**
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * e1000_read_phy_reg_m88 - Read m88 PHY register
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @hw: pointer to the HW structure
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @offset: register offset to be read
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @data: pointer to the read data
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi *
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * Acquires semaphore, if necessary, then reads the PHY register at offset
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * and storing the retrieved information in data. Release any acquired
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * semaphores before exiting.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi **/
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchis32 e1000_read_phy_reg_m88(struct e1000_hw *hw, u32 offset, u16 *data)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi{
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi s32 ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGFUNC("e1000_read_phy_reg_m88");
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (!hw->phy.ops.acquire)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return E1000_SUCCESS;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = hw->phy.ops.acquire(hw);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (ret_val)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = e1000_read_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset,
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi data);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi hw->phy.ops.release(hw);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi}
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi/**
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * e1000_write_phy_reg_m88 - Write m88 PHY register
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @hw: pointer to the HW structure
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @offset: register offset to write to
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @data: data to write at register offset
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi *
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * Acquires semaphore, if necessary, then writes the data to PHY register
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * at the offset. Release any acquired semaphores before exiting.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi **/
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchis32 e1000_write_phy_reg_m88(struct e1000_hw *hw, u32 offset, u16 data)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi{
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi s32 ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGFUNC("e1000_write_phy_reg_m88");
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (!hw->phy.ops.acquire)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return E1000_SUCCESS;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = hw->phy.ops.acquire(hw);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (ret_val)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = e1000_write_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset,
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi data);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi hw->phy.ops.release(hw);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi}
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi/**
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * e1000_set_page_igp - Set page as on IGP-like PHY(s)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @hw: pointer to the HW structure
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @page: page to set (shifted left when necessary)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi *
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * Sets PHY page required for PHY register access. Assumes semaphore is
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * already acquired. Note, this function sets phy.addr to 1 so the caller
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * must set it appropriately (if necessary) after this function returns.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi **/
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchis32 e1000_set_page_igp(struct e1000_hw *hw, u16 page)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi{
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGFUNC("e1000_set_page_igp");
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGOUT1("Setting page 0x%x\n", page);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi hw->phy.addr = 1;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return e1000_write_phy_reg_mdic(hw, IGP01E1000_PHY_PAGE_SELECT, page);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi}
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi/**
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * __e1000_read_phy_reg_igp - Read igp PHY register
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @hw: pointer to the HW structure
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @offset: register offset to be read
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @data: pointer to the read data
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @locked: semaphore has already been acquired or not
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi *
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * Acquires semaphore, if necessary, then reads the PHY register at offset
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * and stores the retrieved information in data. Release any acquired
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * semaphores before exiting.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi **/
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchistatic s32 __e1000_read_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 *data,
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi bool locked)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi{
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi s32 ret_val = E1000_SUCCESS;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGFUNC("__e1000_read_phy_reg_igp");
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (!locked) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (!hw->phy.ops.acquire)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return E1000_SUCCESS;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = hw->phy.ops.acquire(hw);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (ret_val)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (offset > MAX_PHY_MULTI_PAGE_REG)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = e1000_write_phy_reg_mdic(hw,
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi IGP01E1000_PHY_PAGE_SELECT,
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi (u16)offset);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (!ret_val)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = e1000_read_phy_reg_mdic(hw,
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi MAX_PHY_REG_ADDRESS & offset,
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi data);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (!locked)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi hw->phy.ops.release(hw);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi}
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi/**
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * e1000_read_phy_reg_igp - Read igp PHY register
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @hw: pointer to the HW structure
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @offset: register offset to be read
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @data: pointer to the read data
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi *
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * Acquires semaphore then reads the PHY register at offset and stores the
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * retrieved information in data.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * Release the acquired semaphore before exiting.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi **/
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchis32 e1000_read_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 *data)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi{
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return __e1000_read_phy_reg_igp(hw, offset, data, FALSE);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi}
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi/**
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * e1000_read_phy_reg_igp_locked - Read igp PHY register
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @hw: pointer to the HW structure
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @offset: register offset to be read
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @data: pointer to the read data
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi *
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * Reads the PHY register at offset and stores the retrieved information
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * in data. Assumes semaphore already acquired.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi **/
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchis32 e1000_read_phy_reg_igp_locked(struct e1000_hw *hw, u32 offset, u16 *data)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi{
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return __e1000_read_phy_reg_igp(hw, offset, data, TRUE);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi}
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi/**
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * e1000_write_phy_reg_igp - Write igp PHY register
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @hw: pointer to the HW structure
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @offset: register offset to write to
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @data: data to write at register offset
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @locked: semaphore has already been acquired or not
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi *
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * Acquires semaphore, if necessary, then writes the data to PHY register
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * at the offset. Release any acquired semaphores before exiting.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi **/
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchistatic s32 __e1000_write_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 data,
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi bool locked)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi{
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi s32 ret_val = E1000_SUCCESS;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGFUNC("e1000_write_phy_reg_igp");
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (!locked) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (!hw->phy.ops.acquire)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return E1000_SUCCESS;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = hw->phy.ops.acquire(hw);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (ret_val)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (offset > MAX_PHY_MULTI_PAGE_REG)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = e1000_write_phy_reg_mdic(hw,
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi IGP01E1000_PHY_PAGE_SELECT,
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi (u16)offset);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (!ret_val)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = e1000_write_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS &
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi offset,
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi data);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (!locked)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi hw->phy.ops.release(hw);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi}
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi/**
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * e1000_write_phy_reg_igp - Write igp PHY register
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @hw: pointer to the HW structure
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @offset: register offset to write to
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @data: data to write at register offset
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi *
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * Acquires semaphore then writes the data to PHY register
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * at the offset. Release any acquired semaphores before exiting.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi **/
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchis32 e1000_write_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 data)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi{
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return __e1000_write_phy_reg_igp(hw, offset, data, FALSE);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi}
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi/**
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * e1000_write_phy_reg_igp_locked - Write igp PHY register
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @hw: pointer to the HW structure
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @offset: register offset to write to
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @data: data to write at register offset
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi *
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * Writes the data to PHY register at the offset.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * Assumes semaphore already acquired.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi **/
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchis32 e1000_write_phy_reg_igp_locked(struct e1000_hw *hw, u32 offset, u16 data)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi{
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return __e1000_write_phy_reg_igp(hw, offset, data, TRUE);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi}
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi/**
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * __e1000_read_kmrn_reg - Read kumeran register
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @hw: pointer to the HW structure
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @offset: register offset to be read
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @data: pointer to the read data
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @locked: semaphore has already been acquired or not
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi *
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * Acquires semaphore, if necessary. Then reads the PHY register at offset
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * using the kumeran interface. The information retrieved is stored in data.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * Release any acquired semaphores before exiting.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi **/
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchistatic s32 __e1000_read_kmrn_reg(struct e1000_hw *hw, u32 offset, u16 *data,
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi bool locked)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi{
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi u32 kmrnctrlsta;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGFUNC("__e1000_read_kmrn_reg");
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (!locked) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi s32 ret_val = E1000_SUCCESS;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (!hw->phy.ops.acquire)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return E1000_SUCCESS;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = hw->phy.ops.acquire(hw);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (ret_val)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi kmrnctrlsta = ((offset << E1000_KMRNCTRLSTA_OFFSET_SHIFT) &
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi E1000_KMRNCTRLSTA_OFFSET) | E1000_KMRNCTRLSTA_REN;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi E1000_WRITE_REG(hw, E1000_KMRNCTRLSTA, kmrnctrlsta);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi E1000_WRITE_FLUSH(hw);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi usec_delay(2);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi kmrnctrlsta = E1000_READ_REG(hw, E1000_KMRNCTRLSTA);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi *data = (u16)kmrnctrlsta;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (!locked)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi hw->phy.ops.release(hw);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return E1000_SUCCESS;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi}
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi/**
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * e1000_read_kmrn_reg_generic - Read kumeran register
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @hw: pointer to the HW structure
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @offset: register offset to be read
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @data: pointer to the read data
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi *
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * Acquires semaphore then reads the PHY register at offset using the
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * kumeran interface. The information retrieved is stored in data.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * Release the acquired semaphore before exiting.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi **/
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchis32 e1000_read_kmrn_reg_generic(struct e1000_hw *hw, u32 offset, u16 *data)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi{
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return __e1000_read_kmrn_reg(hw, offset, data, FALSE);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi}
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi/**
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * e1000_read_kmrn_reg_locked - Read kumeran register
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @hw: pointer to the HW structure
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @offset: register offset to be read
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @data: pointer to the read data
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi *
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * Reads the PHY register at offset using the kumeran interface. The
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * information retrieved is stored in data.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * Assumes semaphore already acquired.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi **/
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchis32 e1000_read_kmrn_reg_locked(struct e1000_hw *hw, u32 offset, u16 *data)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi{
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return __e1000_read_kmrn_reg(hw, offset, data, TRUE);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi}
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi/**
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * __e1000_write_kmrn_reg - Write kumeran register
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @hw: pointer to the HW structure
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @offset: register offset to write to
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @data: data to write at register offset
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @locked: semaphore has already been acquired or not
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi *
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * Acquires semaphore, if necessary. Then write the data to PHY register
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * at the offset using the kumeran interface. Release any acquired semaphores
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * before exiting.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi **/
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchistatic s32 __e1000_write_kmrn_reg(struct e1000_hw *hw, u32 offset, u16 data,
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi bool locked)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi{
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi u32 kmrnctrlsta;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGFUNC("e1000_write_kmrn_reg_generic");
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (!locked) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi s32 ret_val = E1000_SUCCESS;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (!hw->phy.ops.acquire)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return E1000_SUCCESS;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = hw->phy.ops.acquire(hw);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (ret_val)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi kmrnctrlsta = ((offset << E1000_KMRNCTRLSTA_OFFSET_SHIFT) &
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi E1000_KMRNCTRLSTA_OFFSET) | data;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi E1000_WRITE_REG(hw, E1000_KMRNCTRLSTA, kmrnctrlsta);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi E1000_WRITE_FLUSH(hw);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi usec_delay(2);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (!locked)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi hw->phy.ops.release(hw);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return E1000_SUCCESS;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi}
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi/**
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * e1000_write_kmrn_reg_generic - Write kumeran register
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @hw: pointer to the HW structure
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @offset: register offset to write to
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @data: data to write at register offset
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi *
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * Acquires semaphore then writes the data to the PHY register at the offset
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * using the kumeran interface. Release the acquired semaphore before exiting.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi **/
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchis32 e1000_write_kmrn_reg_generic(struct e1000_hw *hw, u32 offset, u16 data)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi{
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return __e1000_write_kmrn_reg(hw, offset, data, FALSE);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi}
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi/**
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * e1000_write_kmrn_reg_locked - Write kumeran register
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @hw: pointer to the HW structure
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @offset: register offset to write to
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @data: data to write at register offset
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi *
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * Write the data to PHY register at the offset using the kumeran interface.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * Assumes semaphore already acquired.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi **/
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchis32 e1000_write_kmrn_reg_locked(struct e1000_hw *hw, u32 offset, u16 data)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi{
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return __e1000_write_kmrn_reg(hw, offset, data, TRUE);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi}
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi/**
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * e1000_set_master_slave_mode - Setup PHY for Master/slave mode
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @hw: pointer to the HW structure
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi *
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * Sets up Master/slave mode
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi **/
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchistatic s32 e1000_set_master_slave_mode(struct e1000_hw *hw)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi{
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi s32 ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi u16 phy_data;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* Resolve Master/Slave mode */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = hw->phy.ops.read_reg(hw, PHY_1000T_CTRL, &phy_data);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (ret_val)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* load defaults for future use */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi hw->phy.original_ms_type = (phy_data & CR_1000T_MS_ENABLE) ?
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ((phy_data & CR_1000T_MS_VALUE) ?
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi e1000_ms_force_master :
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi e1000_ms_force_slave) : e1000_ms_auto;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi switch (hw->phy.ms_type) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi case e1000_ms_force_master:
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi phy_data |= (CR_1000T_MS_ENABLE | CR_1000T_MS_VALUE);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi break;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi case e1000_ms_force_slave:
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi phy_data |= CR_1000T_MS_ENABLE;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi phy_data &= ~(CR_1000T_MS_VALUE);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi break;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi case e1000_ms_auto:
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi phy_data &= ~CR_1000T_MS_ENABLE;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* fall-through */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi default:
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi break;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return hw->phy.ops.write_reg(hw, PHY_1000T_CTRL, phy_data);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi}
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi/**
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * e1000_copper_link_setup_82577 - Setup 82577 PHY for copper link
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @hw: pointer to the HW structure
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi *
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * Sets up Carrier-sense on Transmit and downshift values.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi **/
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchis32 e1000_copper_link_setup_82577(struct e1000_hw *hw)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi{
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi s32 ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi u16 phy_data;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGFUNC("e1000_copper_link_setup_82577");
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (hw->phy.type == e1000_phy_82580) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = hw->phy.ops.reset(hw);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (ret_val) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGOUT("Error resetting the PHY.\n");
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi /* Enable CRS on Tx. This must be set for half-duplex operation. */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = hw->phy.ops.read_reg(hw, I82577_CFG_REG, &phy_data);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (ret_val)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi phy_data |= I82577_CFG_ASSERT_CRS_ON_TX;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* Enable downshift */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi phy_data |= I82577_CFG_ENABLE_DOWNSHIFT;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = hw->phy.ops.write_reg(hw, I82577_CFG_REG, phy_data);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (ret_val)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* Set MDI/MDIX mode */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = hw->phy.ops.read_reg(hw, I82577_PHY_CTRL_2, &phy_data);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (ret_val)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi phy_data &= ~I82577_PHY_CTRL2_MDIX_CFG_MASK;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* Options:
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * 0 - Auto (default)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * 1 - MDI mode
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * 2 - MDI-X mode
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi switch (hw->phy.mdix) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi case 1:
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi break;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi case 2:
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi phy_data |= I82577_PHY_CTRL2_MANUAL_MDIX;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi break;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi case 0:
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi default:
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi phy_data |= I82577_PHY_CTRL2_AUTO_MDI_MDIX;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi break;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = hw->phy.ops.write_reg(hw, I82577_PHY_CTRL_2, phy_data);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (ret_val)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return e1000_set_master_slave_mode(hw);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi}
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi/**
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * e1000_copper_link_setup_m88 - Setup m88 PHY's for copper link
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @hw: pointer to the HW structure
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi *
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * Sets up MDI/MDI-X and polarity for m88 PHY's. If necessary, transmit clock
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * and downshift values are set also.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi **/
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchis32 e1000_copper_link_setup_m88(struct e1000_hw *hw)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi{
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi struct e1000_phy_info *phy = &hw->phy;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi s32 ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi u16 phy_data;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGFUNC("e1000_copper_link_setup_m88");
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* Enable CRS on Tx. This must be set for half-duplex operation. */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = phy->ops.read_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (ret_val)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* For BM PHY this bit is downshift enable */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (phy->type != e1000_phy_bm)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi phy_data |= M88E1000_PSCR_ASSERT_CRS_ON_TX;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* Options:
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * MDI/MDI-X = 0 (default)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * 0 - Auto for all speeds
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * 1 - MDI mode
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * 2 - MDI-X mode
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * 3 - Auto for 1000Base-T only (MDI-X for 10/100Base-T modes)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi phy_data &= ~M88E1000_PSCR_AUTO_X_MODE;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi switch (phy->mdix) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi case 1:
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi phy_data |= M88E1000_PSCR_MDI_MANUAL_MODE;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi break;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi case 2:
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi phy_data |= M88E1000_PSCR_MDIX_MANUAL_MODE;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi break;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi case 3:
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi phy_data |= M88E1000_PSCR_AUTO_X_1000T;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi break;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi case 0:
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi default:
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi phy_data |= M88E1000_PSCR_AUTO_X_MODE;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi break;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* Options:
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * disable_polarity_correction = 0 (default)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * Automatic Correction for Reversed Cable Polarity
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * 0 - Disabled
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * 1 - Enabled
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi phy_data &= ~M88E1000_PSCR_POLARITY_REVERSAL;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (phy->disable_polarity_correction)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi phy_data |= M88E1000_PSCR_POLARITY_REVERSAL;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* Enable downshift on BM (disabled by default) */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (phy->type == e1000_phy_bm) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* For 82574/82583, first disable then enable downshift */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (phy->id == BME1000_E_PHY_ID_R2) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi phy_data &= ~BME1000_PSCR_ENABLE_DOWNSHIFT;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = phy->ops.write_reg(hw, M88E1000_PHY_SPEC_CTRL,
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi phy_data);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (ret_val)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* Commit the changes. */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = phy->ops.commit(hw);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (ret_val) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGOUT("Error committing the PHY changes\n");
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi phy_data |= BME1000_PSCR_ENABLE_DOWNSHIFT;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = phy->ops.write_reg(hw, M88E1000_PHY_SPEC_CTRL, phy_data);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (ret_val)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if ((phy->type == e1000_phy_m88) &&
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi (phy->revision < E1000_REVISION_4) &&
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi (phy->id != BME1000_E_PHY_ID_R2)) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* Force TX_CLK in the Extended PHY Specific Control Register
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * to 25MHz clock.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = phy->ops.read_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL,
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi &phy_data);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (ret_val)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi phy_data |= M88E1000_EPSCR_TX_CLK_25;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if ((phy->revision == E1000_REVISION_2) &&
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi (phy->id == M88E1111_I_PHY_ID)) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* 82573L PHY - set the downshift counter to 5x. */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi phy_data &= ~M88EC018_EPSCR_DOWNSHIFT_COUNTER_MASK;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi phy_data |= M88EC018_EPSCR_DOWNSHIFT_COUNTER_5X;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi } else {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* Configure Master and Slave downshift values */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi phy_data &= ~(M88E1000_EPSCR_MASTER_DOWNSHIFT_MASK |
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi M88E1000_EPSCR_SLAVE_DOWNSHIFT_MASK);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi phy_data |= (M88E1000_EPSCR_MASTER_DOWNSHIFT_1X |
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi M88E1000_EPSCR_SLAVE_DOWNSHIFT_1X);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = phy->ops.write_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL,
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi phy_data);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (ret_val)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if ((phy->type == e1000_phy_bm) && (phy->id == BME1000_E_PHY_ID_R2)) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* Set PHY page 0, register 29 to 0x0003 */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = phy->ops.write_reg(hw, 29, 0x0003);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (ret_val)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* Set PHY page 0, register 30 to 0x0000 */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = phy->ops.write_reg(hw, 30, 0x0000);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (ret_val)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* Commit the changes. */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = phy->ops.commit(hw);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (ret_val) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGOUT("Error committing the PHY changes\n");
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (phy->type == e1000_phy_82578) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = phy->ops.read_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL,
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi &phy_data);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (ret_val)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* 82578 PHY - set the downshift count to 1x. */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi phy_data |= I82578_EPSCR_DOWNSHIFT_ENABLE;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi phy_data &= ~I82578_EPSCR_DOWNSHIFT_COUNTER_MASK;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = phy->ops.write_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL,
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi phy_data);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (ret_val)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return E1000_SUCCESS;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi}
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi/**
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * e1000_copper_link_setup_m88_gen2 - Setup m88 PHY's for copper link
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @hw: pointer to the HW structure
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi *
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * Sets up MDI/MDI-X and polarity for i347-AT4, m88e1322 and m88e1112 PHY's.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * Also enables and sets the downshift parameters.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi **/
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchis32 e1000_copper_link_setup_m88_gen2(struct e1000_hw *hw)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi{
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi struct e1000_phy_info *phy = &hw->phy;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi s32 ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi u16 phy_data;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGFUNC("e1000_copper_link_setup_m88_gen2");
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* Enable CRS on Tx. This must be set for half-duplex operation. */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = phy->ops.read_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (ret_val)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* Options:
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * MDI/MDI-X = 0 (default)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * 0 - Auto for all speeds
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * 1 - MDI mode
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * 2 - MDI-X mode
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * 3 - Auto for 1000Base-T only (MDI-X for 10/100Base-T modes)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi phy_data &= ~M88E1000_PSCR_AUTO_X_MODE;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi switch (phy->mdix) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi case 1:
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi phy_data |= M88E1000_PSCR_MDI_MANUAL_MODE;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi break;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi case 2:
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi phy_data |= M88E1000_PSCR_MDIX_MANUAL_MODE;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi break;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi case 3:
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* M88E1112 does not support this mode) */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (phy->id != M88E1112_E_PHY_ID) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi phy_data |= M88E1000_PSCR_AUTO_X_1000T;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi break;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi case 0:
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi default:
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi phy_data |= M88E1000_PSCR_AUTO_X_MODE;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi break;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* Options:
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * disable_polarity_correction = 0 (default)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * Automatic Correction for Reversed Cable Polarity
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * 0 - Disabled
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * 1 - Enabled
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi phy_data &= ~M88E1000_PSCR_POLARITY_REVERSAL;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (phy->disable_polarity_correction)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi phy_data |= M88E1000_PSCR_POLARITY_REVERSAL;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* Enable downshift and setting it to X6 */
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi if (phy->id == M88E1543_E_PHY_ID) {
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi phy_data &= ~I347AT4_PSCR_DOWNSHIFT_ENABLE;
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi ret_val =
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi phy->ops.write_reg(hw, M88E1000_PHY_SPEC_CTRL, phy_data);
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi if (ret_val)
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi return ret_val;
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi ret_val = phy->ops.commit(hw);
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi if (ret_val) {
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi DEBUGOUT("Error committing the PHY changes\n");
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi return ret_val;
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi }
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi }
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi phy_data &= ~I347AT4_PSCR_DOWNSHIFT_MASK;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi phy_data |= I347AT4_PSCR_DOWNSHIFT_6X;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi phy_data |= I347AT4_PSCR_DOWNSHIFT_ENABLE;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = phy->ops.write_reg(hw, M88E1000_PHY_SPEC_CTRL, phy_data);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (ret_val)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* Commit the changes. */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = phy->ops.commit(hw);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (ret_val) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGOUT("Error committing the PHY changes\n");
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi ret_val = e1000_set_master_slave_mode(hw);
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi if (ret_val)
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi return ret_val;
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return E1000_SUCCESS;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi}
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi/**
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * e1000_copper_link_setup_igp - Setup igp PHY's for copper link
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @hw: pointer to the HW structure
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi *
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * Sets up LPLU, MDI/MDI-X, polarity, Smartspeed and Master/Slave config for
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * igp PHY's.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi **/
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchis32 e1000_copper_link_setup_igp(struct e1000_hw *hw)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi{
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi struct e1000_phy_info *phy = &hw->phy;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi s32 ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi u16 data;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGFUNC("e1000_copper_link_setup_igp");
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = hw->phy.ops.reset(hw);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (ret_val) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGOUT("Error resetting the PHY.\n");
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* Wait 100ms for MAC to configure PHY from NVM settings, to avoid
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * timeout issues when LFS is enabled.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi msec_delay(100);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* The NVM settings will configure LPLU in D3 for
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * non-IGP1 PHYs.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (phy->type == e1000_phy_igp) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* disable lplu d3 during driver init */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = hw->phy.ops.set_d3_lplu_state(hw, FALSE);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (ret_val) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGOUT("Error Disabling LPLU D3\n");
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* disable lplu d0 during driver init */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (hw->phy.ops.set_d0_lplu_state) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = hw->phy.ops.set_d0_lplu_state(hw, FALSE);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (ret_val) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGOUT("Error Disabling LPLU D0\n");
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* Configure mdi-mdix settings */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = phy->ops.read_reg(hw, IGP01E1000_PHY_PORT_CTRL, &data);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (ret_val)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi data &= ~IGP01E1000_PSCR_AUTO_MDIX;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi switch (phy->mdix) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi case 1:
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi data &= ~IGP01E1000_PSCR_FORCE_MDI_MDIX;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi break;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi case 2:
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi data |= IGP01E1000_PSCR_FORCE_MDI_MDIX;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi break;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi case 0:
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi default:
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi data |= IGP01E1000_PSCR_AUTO_MDIX;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi break;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = phy->ops.write_reg(hw, IGP01E1000_PHY_PORT_CTRL, data);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (ret_val)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* set auto-master slave resolution settings */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (hw->mac.autoneg) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* when autonegotiation advertisement is only 1000Mbps then we
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * should disable SmartSpeed and enable Auto MasterSlave
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * resolution as hardware default.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (phy->autoneg_advertised == ADVERTISE_1000_FULL) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* Disable SmartSpeed */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = phy->ops.read_reg(hw,
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi IGP01E1000_PHY_PORT_CONFIG,
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi &data);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (ret_val)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi data &= ~IGP01E1000_PSCFR_SMART_SPEED;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = phy->ops.write_reg(hw,
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi IGP01E1000_PHY_PORT_CONFIG,
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi data);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (ret_val)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* Set auto Master/Slave resolution process */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = phy->ops.read_reg(hw, PHY_1000T_CTRL, &data);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (ret_val)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi data &= ~CR_1000T_MS_ENABLE;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = phy->ops.write_reg(hw, PHY_1000T_CTRL, data);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (ret_val)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = e1000_set_master_slave_mode(hw);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi}
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi/**
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * e1000_phy_setup_autoneg - Configure PHY for auto-negotiation
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @hw: pointer to the HW structure
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi *
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * Reads the MII auto-neg advertisement register and/or the 1000T control
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * register and if the PHY is already setup for auto-negotiation, then
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * return successful. Otherwise, setup advertisement and flow control to
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * the appropriate values for the wanted auto-negotiation.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi **/
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchis32 e1000_phy_setup_autoneg(struct e1000_hw *hw)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi{
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi struct e1000_phy_info *phy = &hw->phy;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi s32 ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi u16 mii_autoneg_adv_reg;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi u16 mii_1000t_ctrl_reg = 0;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGFUNC("e1000_phy_setup_autoneg");
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi phy->autoneg_advertised &= phy->autoneg_mask;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* Read the MII Auto-Neg Advertisement Register (Address 4). */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = phy->ops.read_reg(hw, PHY_AUTONEG_ADV, &mii_autoneg_adv_reg);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (ret_val)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (phy->autoneg_mask & ADVERTISE_1000_FULL) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* Read the MII 1000Base-T Control Register (Address 9). */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = phy->ops.read_reg(hw, PHY_1000T_CTRL,
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi &mii_1000t_ctrl_reg);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (ret_val)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* Need to parse both autoneg_advertised and fc and set up
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * the appropriate PHY registers. First we will parse for
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * autoneg_advertised software override. Since we can advertise
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * a plethora of combinations, we need to check each bit
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * individually.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* First we clear all the 10/100 mb speed bits in the Auto-Neg
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * Advertisement Register (Address 4) and the 1000 mb speed bits in
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * the 1000Base-T Control Register (Address 9).
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi mii_autoneg_adv_reg &= ~(NWAY_AR_100TX_FD_CAPS |
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi NWAY_AR_100TX_HD_CAPS |
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi NWAY_AR_10T_FD_CAPS |
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi NWAY_AR_10T_HD_CAPS);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi mii_1000t_ctrl_reg &= ~(CR_1000T_HD_CAPS | CR_1000T_FD_CAPS);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGOUT1("autoneg_advertised %x\n", phy->autoneg_advertised);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* Do we want to advertise 10 Mb Half Duplex? */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (phy->autoneg_advertised & ADVERTISE_10_HALF) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGOUT("Advertise 10mb Half duplex\n");
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi mii_autoneg_adv_reg |= NWAY_AR_10T_HD_CAPS;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* Do we want to advertise 10 Mb Full Duplex? */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (phy->autoneg_advertised & ADVERTISE_10_FULL) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGOUT("Advertise 10mb Full duplex\n");
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi mii_autoneg_adv_reg |= NWAY_AR_10T_FD_CAPS;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* Do we want to advertise 100 Mb Half Duplex? */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (phy->autoneg_advertised & ADVERTISE_100_HALF) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGOUT("Advertise 100mb Half duplex\n");
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi mii_autoneg_adv_reg |= NWAY_AR_100TX_HD_CAPS;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* Do we want to advertise 100 Mb Full Duplex? */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (phy->autoneg_advertised & ADVERTISE_100_FULL) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGOUT("Advertise 100mb Full duplex\n");
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi mii_autoneg_adv_reg |= NWAY_AR_100TX_FD_CAPS;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* We do not allow the Phy to advertise 1000 Mb Half Duplex */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (phy->autoneg_advertised & ADVERTISE_1000_HALF)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGOUT("Advertise 1000mb Half duplex request denied!\n");
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* Do we want to advertise 1000 Mb Full Duplex? */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (phy->autoneg_advertised & ADVERTISE_1000_FULL) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGOUT("Advertise 1000mb Full duplex\n");
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi mii_1000t_ctrl_reg |= CR_1000T_FD_CAPS;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* Check for a software override of the flow control settings, and
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * setup the PHY advertisement registers accordingly. If
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * auto-negotiation is enabled, then software will have to set the
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * "PAUSE" bits to the correct value in the Auto-Negotiation
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * Advertisement Register (PHY_AUTONEG_ADV) and re-start auto-
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * negotiation.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi *
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * The possible values of the "fc" parameter are:
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * 0: Flow control is completely disabled
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * 1: Rx flow control is enabled (we can receive pause frames
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * but not send pause frames).
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * 2: Tx flow control is enabled (we can send pause frames
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * but we do not support receiving pause frames).
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * 3: Both Rx and Tx flow control (symmetric) are enabled.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * other: No software override. The flow control configuration
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * in the EEPROM is used.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi switch (hw->fc.current_mode) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi case e1000_fc_none:
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* Flow control (Rx & Tx) is completely disabled by a
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * software over-ride.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi mii_autoneg_adv_reg &= ~(NWAY_AR_ASM_DIR | NWAY_AR_PAUSE);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi break;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi case e1000_fc_rx_pause:
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* Rx Flow control is enabled, and Tx Flow control is
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * disabled, by a software over-ride.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi *
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * Since there really isn't a way to advertise that we are
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * capable of Rx Pause ONLY, we will advertise that we
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * support both symmetric and asymmetric Rx PAUSE. Later
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * (in e1000_config_fc_after_link_up) we will disable the
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * hw's ability to send PAUSE frames.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi mii_autoneg_adv_reg |= (NWAY_AR_ASM_DIR | NWAY_AR_PAUSE);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi break;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi case e1000_fc_tx_pause:
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* Tx Flow control is enabled, and Rx Flow control is
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * disabled, by a software over-ride.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi mii_autoneg_adv_reg |= NWAY_AR_ASM_DIR;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi mii_autoneg_adv_reg &= ~NWAY_AR_PAUSE;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi break;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi case e1000_fc_full:
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* Flow control (both Rx and Tx) is enabled by a software
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * over-ride.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi mii_autoneg_adv_reg |= (NWAY_AR_ASM_DIR | NWAY_AR_PAUSE);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi break;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi default:
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGOUT("Flow control param set incorrectly\n");
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return -E1000_ERR_CONFIG;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = phy->ops.write_reg(hw, PHY_AUTONEG_ADV, mii_autoneg_adv_reg);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (ret_val)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGOUT1("Auto-Neg Advertising %x\n", mii_autoneg_adv_reg);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (phy->autoneg_mask & ADVERTISE_1000_FULL)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = phy->ops.write_reg(hw, PHY_1000T_CTRL,
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi mii_1000t_ctrl_reg);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi}
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi/**
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * e1000_copper_link_autoneg - Setup/Enable autoneg for copper link
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @hw: pointer to the HW structure
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi *
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * Performs initial bounds checking on autoneg advertisement parameter, then
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * configure to advertise the full capability. Setup the PHY to autoneg
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * and restart the negotiation process between the link partner. If
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * autoneg_wait_to_complete, then wait for autoneg to complete before exiting.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi **/
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchis32 e1000_copper_link_autoneg(struct e1000_hw *hw)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi{
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi struct e1000_phy_info *phy = &hw->phy;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi s32 ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi u16 phy_ctrl;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGFUNC("e1000_copper_link_autoneg");
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* Perform some bounds checking on the autoneg advertisement
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * parameter.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi phy->autoneg_advertised &= phy->autoneg_mask;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* If autoneg_advertised is zero, we assume it was not defaulted
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * by the calling code so we set to advertise full capability.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (!phy->autoneg_advertised)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi phy->autoneg_advertised = phy->autoneg_mask;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGOUT("Reconfiguring auto-neg advertisement params\n");
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = e1000_phy_setup_autoneg(hw);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (ret_val) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGOUT("Error Setting up Auto-Negotiation\n");
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGOUT("Restarting Auto-Neg\n");
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* Restart auto-negotiation by setting the Auto Neg Enable bit and
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * the Auto Neg Restart bit in the PHY control register.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = phy->ops.read_reg(hw, PHY_CONTROL, &phy_ctrl);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (ret_val)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi phy_ctrl |= (MII_CR_AUTO_NEG_EN | MII_CR_RESTART_AUTO_NEG);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = phy->ops.write_reg(hw, PHY_CONTROL, phy_ctrl);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (ret_val)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* Does the user want to wait for Auto-Neg to complete here, or
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * check at a later time (for example, callback routine).
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (phy->autoneg_wait_to_complete) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = e1000_wait_autoneg(hw);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (ret_val) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGOUT("Error while waiting for autoneg to complete\n");
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi hw->mac.get_link_status = TRUE;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi}
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi/**
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * e1000_setup_copper_link_generic - Configure copper link settings
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @hw: pointer to the HW structure
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi *
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * Calls the appropriate function to configure the link for auto-neg or forced
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * speed and duplex. Then we check for link, once link is established calls
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * to configure collision distance and flow control are called. If link is
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * not established, we return -E1000_ERR_PHY (-2).
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi **/
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchis32 e1000_setup_copper_link_generic(struct e1000_hw *hw)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi{
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi s32 ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi bool link;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGFUNC("e1000_setup_copper_link_generic");
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (hw->mac.autoneg) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* Setup autoneg and flow control advertisement and perform
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * autonegotiation.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = e1000_copper_link_autoneg(hw);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (ret_val)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi } else {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* PHY will be set to 10H, 10F, 100H or 100F
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * depending on user settings.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGOUT("Forcing Speed and Duplex\n");
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = hw->phy.ops.force_speed_duplex(hw);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (ret_val) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGOUT("Error Forcing Speed and Duplex\n");
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* Check link status. Wait up to 100 microseconds for link to become
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * valid.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = e1000_phy_has_link_generic(hw, COPPER_LINK_UP_LIMIT, 10,
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi &link);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (ret_val)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (link) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGOUT("Valid link established!!!\n");
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi hw->mac.ops.config_collision_dist(hw);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = e1000_config_fc_after_link_up_generic(hw);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi } else {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGOUT("Unable to establish link!!!\n");
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi}
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi/**
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * e1000_phy_force_speed_duplex_igp - Force speed/duplex for igp PHY
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @hw: pointer to the HW structure
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi *
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * Calls the PHY setup function to force speed and duplex. Clears the
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * auto-crossover to force MDI manually. Waits for link and returns
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * successful if link up is successful, else -E1000_ERR_PHY (-2).
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi **/
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchis32 e1000_phy_force_speed_duplex_igp(struct e1000_hw *hw)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi{
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi struct e1000_phy_info *phy = &hw->phy;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi s32 ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi u16 phy_data;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi bool link;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGFUNC("e1000_phy_force_speed_duplex_igp");
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = phy->ops.read_reg(hw, PHY_CONTROL, &phy_data);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (ret_val)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi e1000_phy_force_speed_duplex_setup(hw, &phy_data);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = phy->ops.write_reg(hw, PHY_CONTROL, phy_data);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (ret_val)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* Clear Auto-Crossover to force MDI manually. IGP requires MDI
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * forced whenever speed and duplex are forced.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = phy->ops.read_reg(hw, IGP01E1000_PHY_PORT_CTRL, &phy_data);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (ret_val)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi phy_data &= ~IGP01E1000_PSCR_AUTO_MDIX;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi phy_data &= ~IGP01E1000_PSCR_FORCE_MDI_MDIX;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = phy->ops.write_reg(hw, IGP01E1000_PHY_PORT_CTRL, phy_data);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (ret_val)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGOUT1("IGP PSCR: %X\n", phy_data);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi usec_delay(1);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (phy->autoneg_wait_to_complete) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGOUT("Waiting for forced speed/duplex link on IGP phy.\n");
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = e1000_phy_has_link_generic(hw, PHY_FORCE_LIMIT,
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi 100000, &link);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (ret_val)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (!link)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGOUT("Link taking longer than expected.\n");
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* Try once more */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = e1000_phy_has_link_generic(hw, PHY_FORCE_LIMIT,
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi 100000, &link);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi}
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi/**
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * e1000_phy_force_speed_duplex_m88 - Force speed/duplex for m88 PHY
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @hw: pointer to the HW structure
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi *
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * Calls the PHY setup function to force speed and duplex. Clears the
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * auto-crossover to force MDI manually. Resets the PHY to commit the
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * changes. If time expires while waiting for link up, we reset the DSP.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * After reset, TX_CLK and CRS on Tx must be set. Return successful upon
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * successful completion, else return corresponding error code.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi **/
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchis32 e1000_phy_force_speed_duplex_m88(struct e1000_hw *hw)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi{
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi struct e1000_phy_info *phy = &hw->phy;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi s32 ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi u16 phy_data;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi bool link;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGFUNC("e1000_phy_force_speed_duplex_m88");
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* I210 and I211 devices support Auto-Crossover in forced operation. */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (phy->type != e1000_phy_i210) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* Clear Auto-Crossover to force MDI manually. M88E1000
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * requires MDI forced whenever speed and duplex are forced.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = phy->ops.read_reg(hw, M88E1000_PHY_SPEC_CTRL,
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi &phy_data);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (ret_val)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi phy_data &= ~M88E1000_PSCR_AUTO_X_MODE;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = phy->ops.write_reg(hw, M88E1000_PHY_SPEC_CTRL,
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi phy_data);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (ret_val)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
49b7860084dbba18bc00b29413d6182197f9fe93Robert Mustacchi DEBUGOUT1("M88E1000 PSCR: %X\n", phy_data);
49b7860084dbba18bc00b29413d6182197f9fe93Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = phy->ops.read_reg(hw, PHY_CONTROL, &phy_data);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (ret_val)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi e1000_phy_force_speed_duplex_setup(hw, &phy_data);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = phy->ops.write_reg(hw, PHY_CONTROL, phy_data);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (ret_val)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* Reset the phy to commit changes. */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = hw->phy.ops.commit(hw);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (ret_val)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (phy->autoneg_wait_to_complete) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGOUT("Waiting for forced speed/duplex link on M88 phy.\n");
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = e1000_phy_has_link_generic(hw, PHY_FORCE_LIMIT,
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi 100000, &link);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (ret_val)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (!link) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi bool reset_dsp = TRUE;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi switch (hw->phy.id) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi case I347AT4_E_PHY_ID:
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi case M88E1340M_E_PHY_ID:
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi case M88E1112_E_PHY_ID:
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi case M88E1543_E_PHY_ID:
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi case M88E1512_E_PHY_ID:
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi case I210_I_PHY_ID:
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi reset_dsp = FALSE;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi break;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi default:
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (hw->phy.type != e1000_phy_m88)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi reset_dsp = FALSE;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi break;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (!reset_dsp) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGOUT("Link taking longer than expected.\n");
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi } else {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* We didn't get link.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * Reset the DSP and cross our fingers.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = phy->ops.write_reg(hw,
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi M88E1000_PHY_PAGE_SELECT,
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi 0x001d);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (ret_val)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = e1000_phy_reset_dsp_generic(hw);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (ret_val)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* Try once more */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = e1000_phy_has_link_generic(hw, PHY_FORCE_LIMIT,
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi 100000, &link);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (ret_val)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (hw->phy.type != e1000_phy_m88)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return E1000_SUCCESS;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (hw->phy.id == I347AT4_E_PHY_ID ||
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi hw->phy.id == M88E1340M_E_PHY_ID ||
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi hw->phy.id == M88E1112_E_PHY_ID)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return E1000_SUCCESS;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (hw->phy.id == I210_I_PHY_ID)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return E1000_SUCCESS;
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi if ((hw->phy.id == M88E1543_E_PHY_ID) ||
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi (hw->phy.id == M88E1512_E_PHY_ID))
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi return E1000_SUCCESS;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = phy->ops.read_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL, &phy_data);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (ret_val)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* Resetting the phy means we need to re-force TX_CLK in the
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * Extended PHY Specific Control Register to 25MHz clock from
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * the reset value of 2.5MHz.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi phy_data |= M88E1000_EPSCR_TX_CLK_25;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = phy->ops.write_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL, phy_data);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (ret_val)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* In addition, we must re-enable CRS on Tx for both half and full
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * duplex.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = phy->ops.read_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (ret_val)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi phy_data |= M88E1000_PSCR_ASSERT_CRS_ON_TX;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = phy->ops.write_reg(hw, M88E1000_PHY_SPEC_CTRL, phy_data);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi}
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi/**
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * e1000_phy_force_speed_duplex_ife - Force PHY speed & duplex
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @hw: pointer to the HW structure
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi *
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * Forces the speed and duplex settings of the PHY.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * This is a function pointer entry point only called by
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * PHY setup routines.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi **/
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchis32 e1000_phy_force_speed_duplex_ife(struct e1000_hw *hw)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi{
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi struct e1000_phy_info *phy = &hw->phy;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi s32 ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi u16 data;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi bool link;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGFUNC("e1000_phy_force_speed_duplex_ife");
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = phy->ops.read_reg(hw, PHY_CONTROL, &data);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (ret_val)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi e1000_phy_force_speed_duplex_setup(hw, &data);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = phy->ops.write_reg(hw, PHY_CONTROL, data);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (ret_val)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* Disable MDI-X support for 10/100 */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = phy->ops.read_reg(hw, IFE_PHY_MDIX_CONTROL, &data);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (ret_val)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi data &= ~IFE_PMC_AUTO_MDIX;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi data &= ~IFE_PMC_FORCE_MDIX;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = phy->ops.write_reg(hw, IFE_PHY_MDIX_CONTROL, data);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (ret_val)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGOUT1("IFE PMC: %X\n", data);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi usec_delay(1);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (phy->autoneg_wait_to_complete) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGOUT("Waiting for forced speed/duplex link on IFE phy.\n");
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = e1000_phy_has_link_generic(hw, PHY_FORCE_LIMIT,
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi 100000, &link);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (ret_val)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (!link)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGOUT("Link taking longer than expected.\n");
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* Try once more */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = e1000_phy_has_link_generic(hw, PHY_FORCE_LIMIT,
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi 100000, &link);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (ret_val)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return E1000_SUCCESS;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi}
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi/**
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * e1000_phy_force_speed_duplex_setup - Configure forced PHY speed/duplex
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @hw: pointer to the HW structure
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @phy_ctrl: pointer to current value of PHY_CONTROL
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi *
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * Forces speed and duplex on the PHY by doing the following: disable flow
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * control, force speed/duplex on the MAC, disable auto speed detection,
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * disable auto-negotiation, configure duplex, configure speed, configure
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * the collision distance, write configuration to CTRL register. The
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * caller must write to the PHY_CONTROL register for these settings to
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * take affect.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi **/
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchivoid e1000_phy_force_speed_duplex_setup(struct e1000_hw *hw, u16 *phy_ctrl)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi{
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi struct e1000_mac_info *mac = &hw->mac;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi u32 ctrl;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGFUNC("e1000_phy_force_speed_duplex_setup");
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* Turn off flow control when forcing speed/duplex */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi hw->fc.current_mode = e1000_fc_none;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* Force speed/duplex on the mac */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ctrl = E1000_READ_REG(hw, E1000_CTRL);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ctrl |= (E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ctrl &= ~E1000_CTRL_SPD_SEL;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* Disable Auto Speed Detection */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ctrl &= ~E1000_CTRL_ASDE;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* Disable autoneg on the phy */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi *phy_ctrl &= ~MII_CR_AUTO_NEG_EN;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* Forcing Full or Half Duplex? */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (mac->forced_speed_duplex & E1000_ALL_HALF_DUPLEX) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ctrl &= ~E1000_CTRL_FD;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi *phy_ctrl &= ~MII_CR_FULL_DUPLEX;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGOUT("Half Duplex\n");
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi } else {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ctrl |= E1000_CTRL_FD;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi *phy_ctrl |= MII_CR_FULL_DUPLEX;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGOUT("Full Duplex\n");
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* Forcing 10mb or 100mb? */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (mac->forced_speed_duplex & E1000_ALL_100_SPEED) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ctrl |= E1000_CTRL_SPD_100;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi *phy_ctrl |= MII_CR_SPEED_100;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi *phy_ctrl &= ~MII_CR_SPEED_1000;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGOUT("Forcing 100mb\n");
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi } else {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ctrl &= ~(E1000_CTRL_SPD_1000 | E1000_CTRL_SPD_100);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi *phy_ctrl &= ~(MII_CR_SPEED_1000 | MII_CR_SPEED_100);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGOUT("Forcing 10mb\n");
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi hw->mac.ops.config_collision_dist(hw);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi E1000_WRITE_REG(hw, E1000_CTRL, ctrl);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi}
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi/**
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * e1000_set_d3_lplu_state_generic - Sets low power link up state for D3
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @hw: pointer to the HW structure
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @active: boolean used to enable/disable lplu
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi *
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * Success returns 0, Failure returns 1
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi *
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * The low power link up (lplu) state is set to the power management level D3
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * and SmartSpeed is disabled when active is TRUE, else clear lplu for D3
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * and enable Smartspeed. LPLU and Smartspeed are mutually exclusive. LPLU
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * is used during Dx states where the power conservation is most important.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * During driver activity, SmartSpeed should be enabled so performance is
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * maintained.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi **/
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchis32 e1000_set_d3_lplu_state_generic(struct e1000_hw *hw, bool active)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi{
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi struct e1000_phy_info *phy = &hw->phy;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi s32 ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi u16 data;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGFUNC("e1000_set_d3_lplu_state_generic");
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (!hw->phy.ops.read_reg)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return E1000_SUCCESS;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = phy->ops.read_reg(hw, IGP02E1000_PHY_POWER_MGMT, &data);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (ret_val)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (!active) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi data &= ~IGP02E1000_PM_D3_LPLU;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = phy->ops.write_reg(hw, IGP02E1000_PHY_POWER_MGMT,
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi data);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (ret_val)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* LPLU and SmartSpeed are mutually exclusive. LPLU is used
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * during Dx states where the power conservation is most
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * important. During driver activity we should enable
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * SmartSpeed, so performance is maintained.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (phy->smart_speed == e1000_smart_speed_on) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = phy->ops.read_reg(hw,
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi IGP01E1000_PHY_PORT_CONFIG,
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi &data);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (ret_val)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi data |= IGP01E1000_PSCFR_SMART_SPEED;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = phy->ops.write_reg(hw,
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi IGP01E1000_PHY_PORT_CONFIG,
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi data);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (ret_val)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi } else if (phy->smart_speed == e1000_smart_speed_off) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = phy->ops.read_reg(hw,
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi IGP01E1000_PHY_PORT_CONFIG,
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi &data);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (ret_val)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi data &= ~IGP01E1000_PSCFR_SMART_SPEED;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = phy->ops.write_reg(hw,
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi IGP01E1000_PHY_PORT_CONFIG,
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi data);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (ret_val)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi } else if ((phy->autoneg_advertised == E1000_ALL_SPEED_DUPLEX) ||
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi (phy->autoneg_advertised == E1000_ALL_NOT_GIG) ||
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi (phy->autoneg_advertised == E1000_ALL_10_SPEED)) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi data |= IGP02E1000_PM_D3_LPLU;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = phy->ops.write_reg(hw, IGP02E1000_PHY_POWER_MGMT,
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi data);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (ret_val)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* When LPLU is enabled, we should disable SmartSpeed */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = phy->ops.read_reg(hw, IGP01E1000_PHY_PORT_CONFIG,
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi &data);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (ret_val)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi data &= ~IGP01E1000_PSCFR_SMART_SPEED;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = phy->ops.write_reg(hw, IGP01E1000_PHY_PORT_CONFIG,
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi data);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi}
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi/**
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * e1000_check_downshift_generic - Checks whether a downshift in speed occurred
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @hw: pointer to the HW structure
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi *
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * Success returns 0, Failure returns 1
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi *
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * A downshift is detected by querying the PHY link health.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi **/
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchis32 e1000_check_downshift_generic(struct e1000_hw *hw)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi{
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi struct e1000_phy_info *phy = &hw->phy;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi s32 ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi u16 phy_data, offset, mask;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGFUNC("e1000_check_downshift_generic");
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi switch (phy->type) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi case e1000_phy_i210:
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi case e1000_phy_m88:
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi case e1000_phy_gg82563:
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi case e1000_phy_bm:
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi case e1000_phy_82578:
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi offset = M88E1000_PHY_SPEC_STATUS;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi mask = M88E1000_PSSR_DOWNSHIFT;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi break;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi case e1000_phy_igp:
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi case e1000_phy_igp_2:
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi case e1000_phy_igp_3:
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi offset = IGP01E1000_PHY_LINK_HEALTH;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi mask = IGP01E1000_PLHR_SS_DOWNGRADE;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi break;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi default:
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* speed downshift not supported */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi phy->speed_downgraded = FALSE;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return E1000_SUCCESS;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = phy->ops.read_reg(hw, offset, &phy_data);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (!ret_val)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi phy->speed_downgraded = !!(phy_data & mask);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi}
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi/**
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * e1000_check_polarity_m88 - Checks the polarity.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @hw: pointer to the HW structure
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi *
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * Success returns 0, Failure returns -E1000_ERR_PHY (-2)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi *
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * Polarity is determined based on the PHY specific status register.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi **/
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchis32 e1000_check_polarity_m88(struct e1000_hw *hw)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi{
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi struct e1000_phy_info *phy = &hw->phy;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi s32 ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi u16 data;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGFUNC("e1000_check_polarity_m88");
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = phy->ops.read_reg(hw, M88E1000_PHY_SPEC_STATUS, &data);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (!ret_val)
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi phy->cable_polarity = ((data & M88E1000_PSSR_REV_POLARITY)
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi ? e1000_rev_polarity_reversed
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi : e1000_rev_polarity_normal);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi}
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi/**
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * e1000_check_polarity_igp - Checks the polarity.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @hw: pointer to the HW structure
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi *
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * Success returns 0, Failure returns -E1000_ERR_PHY (-2)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi *
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * Polarity is determined based on the PHY port status register, and the
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * current speed (since there is no polarity at 100Mbps).
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi **/
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchis32 e1000_check_polarity_igp(struct e1000_hw *hw)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi{
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi struct e1000_phy_info *phy = &hw->phy;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi s32 ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi u16 data, offset, mask;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGFUNC("e1000_check_polarity_igp");
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* Polarity is determined based on the speed of
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * our connection.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = phy->ops.read_reg(hw, IGP01E1000_PHY_PORT_STATUS, &data);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (ret_val)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if ((data & IGP01E1000_PSSR_SPEED_MASK) ==
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi IGP01E1000_PSSR_SPEED_1000MBPS) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi offset = IGP01E1000_PHY_PCS_INIT_REG;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi mask = IGP01E1000_PHY_POLARITY_MASK;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi } else {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* This really only applies to 10Mbps since
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * there is no polarity for 100Mbps (always 0).
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi offset = IGP01E1000_PHY_PORT_STATUS;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi mask = IGP01E1000_PSSR_POLARITY_REVERSED;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = phy->ops.read_reg(hw, offset, &data);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (!ret_val)
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi phy->cable_polarity = ((data & mask)
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi ? e1000_rev_polarity_reversed
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi : e1000_rev_polarity_normal);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi}
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi/**
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * e1000_check_polarity_ife - Check cable polarity for IFE PHY
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @hw: pointer to the HW structure
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi *
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * Polarity is determined on the polarity reversal feature being enabled.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi **/
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchis32 e1000_check_polarity_ife(struct e1000_hw *hw)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi{
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi struct e1000_phy_info *phy = &hw->phy;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi s32 ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi u16 phy_data, offset, mask;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGFUNC("e1000_check_polarity_ife");
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* Polarity is determined based on the reversal feature being enabled.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (phy->polarity_correction) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi offset = IFE_PHY_EXTENDED_STATUS_CONTROL;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi mask = IFE_PESC_POLARITY_REVERSED;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi } else {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi offset = IFE_PHY_SPECIAL_CONTROL;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi mask = IFE_PSC_FORCE_POLARITY;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = phy->ops.read_reg(hw, offset, &phy_data);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (!ret_val)
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi phy->cable_polarity = ((phy_data & mask)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ? e1000_rev_polarity_reversed
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi : e1000_rev_polarity_normal);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi}
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi/**
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * e1000_wait_autoneg - Wait for auto-neg completion
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @hw: pointer to the HW structure
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi *
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * Waits for auto-negotiation to complete or for the auto-negotiation time
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * limit to expire, which ever happens first.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi **/
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchistatic s32 e1000_wait_autoneg(struct e1000_hw *hw)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi{
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi s32 ret_val = E1000_SUCCESS;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi u16 i, phy_status;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGFUNC("e1000_wait_autoneg");
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (!hw->phy.ops.read_reg)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return E1000_SUCCESS;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* Break after autoneg completes or PHY_AUTO_NEG_LIMIT expires. */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi for (i = PHY_AUTO_NEG_LIMIT; i > 0; i--) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = hw->phy.ops.read_reg(hw, PHY_STATUS, &phy_status);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (ret_val)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi break;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = hw->phy.ops.read_reg(hw, PHY_STATUS, &phy_status);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (ret_val)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi break;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (phy_status & MII_SR_AUTONEG_COMPLETE)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi break;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi msec_delay(100);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* PHY_AUTO_NEG_TIME expiration doesn't guarantee auto-negotiation
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * has completed.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi}
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi/**
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * e1000_phy_has_link_generic - Polls PHY for link
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @hw: pointer to the HW structure
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @iterations: number of times to poll for link
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @usec_interval: delay between polling attempts
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @success: pointer to whether polling was successful or not
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi *
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * Polls the PHY status register for link, 'iterations' number of times.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi **/
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchis32 e1000_phy_has_link_generic(struct e1000_hw *hw, u32 iterations,
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi u32 usec_interval, bool *success)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi{
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi s32 ret_val = E1000_SUCCESS;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi u16 i, phy_status;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGFUNC("e1000_phy_has_link_generic");
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (!hw->phy.ops.read_reg)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return E1000_SUCCESS;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi for (i = 0; i < iterations; i++) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* Some PHYs require the PHY_STATUS register to be read
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * twice due to the link bit being sticky. No harm doing
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * it across the board.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = hw->phy.ops.read_reg(hw, PHY_STATUS, &phy_status);
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi if (ret_val) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* If the first read fails, another entity may have
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * ownership of the resources, wait and try again to
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * see if they have relinquished the resources yet.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi */
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi if (usec_interval >= 1000)
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi msec_delay(usec_interval/1000);
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi else
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi usec_delay(usec_interval);
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = hw->phy.ops.read_reg(hw, PHY_STATUS, &phy_status);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (ret_val)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi break;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (phy_status & MII_SR_LINK_STATUS)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi break;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (usec_interval >= 1000)
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi msec_delay(usec_interval/1000);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi else
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi usec_delay(usec_interval);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi *success = (i < iterations);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi}
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi/**
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * e1000_get_cable_length_m88 - Determine cable length for m88 PHY
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @hw: pointer to the HW structure
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi *
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * Reads the PHY specific status register to retrieve the cable length
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * information. The cable length is determined by averaging the minimum and
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * maximum values to get the "average" cable length. The m88 PHY has four
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * possible cable length values, which are:
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * Register Value Cable Length
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * 0 < 50 meters
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * 1 50 - 80 meters
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * 2 80 - 110 meters
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * 3 110 - 140 meters
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * 4 > 140 meters
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi **/
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchis32 e1000_get_cable_length_m88(struct e1000_hw *hw)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi{
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi struct e1000_phy_info *phy = &hw->phy;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi s32 ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi u16 phy_data, index;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGFUNC("e1000_get_cable_length_m88");
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = phy->ops.read_reg(hw, M88E1000_PHY_SPEC_STATUS, &phy_data);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (ret_val)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi index = ((phy_data & M88E1000_PSSR_CABLE_LENGTH) >>
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi M88E1000_PSSR_CABLE_LENGTH_SHIFT);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (index >= M88E1000_CABLE_LENGTH_TABLE_SIZE - 1)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return -E1000_ERR_PHY;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi phy->min_cable_length = e1000_m88_cable_length_table[index];
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi phy->max_cable_length = e1000_m88_cable_length_table[index + 1];
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi phy->cable_length = (phy->min_cable_length + phy->max_cable_length) / 2;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return E1000_SUCCESS;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi}
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchis32 e1000_get_cable_length_m88_gen2(struct e1000_hw *hw)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi{
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi struct e1000_phy_info *phy = &hw->phy;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi s32 ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi u16 phy_data, phy_data2, is_cm;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi u16 index, default_page;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGFUNC("e1000_get_cable_length_m88_gen2");
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi switch (hw->phy.id) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi case I210_I_PHY_ID:
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* Get cable length from PHY Cable Diagnostics Control Reg */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = phy->ops.read_reg(hw, (0x7 << GS40G_PAGE_SHIFT) +
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi (I347AT4_PCDL + phy->addr),
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi &phy_data);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (ret_val)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* Check if the unit of cable length is meters or cm */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = phy->ops.read_reg(hw, (0x7 << GS40G_PAGE_SHIFT) +
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi I347AT4_PCDC, &phy_data2);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (ret_val)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi is_cm = !(phy_data2 & I347AT4_PCDC_CABLE_LENGTH_UNIT);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* Populate the phy structure with cable length in meters */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi phy->min_cable_length = phy_data / (is_cm ? 100 : 1);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi phy->max_cable_length = phy_data / (is_cm ? 100 : 1);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi phy->cable_length = phy_data / (is_cm ? 100 : 1);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi break;
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi case M88E1543_E_PHY_ID:
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi case M88E1512_E_PHY_ID:
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi case M88E1340M_E_PHY_ID:
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi case I347AT4_E_PHY_ID:
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* Remember the original page select and set it to 7 */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = phy->ops.read_reg(hw, I347AT4_PAGE_SELECT,
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi &default_page);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (ret_val)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = phy->ops.write_reg(hw, I347AT4_PAGE_SELECT, 0x07);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (ret_val)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* Get cable length from PHY Cable Diagnostics Control Reg */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = phy->ops.read_reg(hw, (I347AT4_PCDL + phy->addr),
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi &phy_data);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (ret_val)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* Check if the unit of cable length is meters or cm */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = phy->ops.read_reg(hw, I347AT4_PCDC, &phy_data2);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (ret_val)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi is_cm = !(phy_data2 & I347AT4_PCDC_CABLE_LENGTH_UNIT);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* Populate the phy structure with cable length in meters */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi phy->min_cable_length = phy_data / (is_cm ? 100 : 1);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi phy->max_cable_length = phy_data / (is_cm ? 100 : 1);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi phy->cable_length = phy_data / (is_cm ? 100 : 1);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* Reset the page select to its original value */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = phy->ops.write_reg(hw, I347AT4_PAGE_SELECT,
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi default_page);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (ret_val)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi break;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi case M88E1112_E_PHY_ID:
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* Remember the original page select and set it to 5 */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = phy->ops.read_reg(hw, I347AT4_PAGE_SELECT,
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi &default_page);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (ret_val)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = phy->ops.write_reg(hw, I347AT4_PAGE_SELECT, 0x05);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (ret_val)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = phy->ops.read_reg(hw, M88E1112_VCT_DSP_DISTANCE,
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi &phy_data);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (ret_val)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi index = (phy_data & M88E1000_PSSR_CABLE_LENGTH) >>
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi M88E1000_PSSR_CABLE_LENGTH_SHIFT;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (index >= M88E1000_CABLE_LENGTH_TABLE_SIZE - 1)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return -E1000_ERR_PHY;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi phy->min_cable_length = e1000_m88_cable_length_table[index];
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi phy->max_cable_length = e1000_m88_cable_length_table[index + 1];
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi phy->cable_length = (phy->min_cable_length +
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi phy->max_cable_length) / 2;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* Reset the page select to its original value */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = phy->ops.write_reg(hw, I347AT4_PAGE_SELECT,
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi default_page);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (ret_val)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi break;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi default:
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return -E1000_ERR_PHY;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi}
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi/**
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * e1000_get_cable_length_igp_2 - Determine cable length for igp2 PHY
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @hw: pointer to the HW structure
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi *
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * The automatic gain control (agc) normalizes the amplitude of the
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * received signal, adjusting for the attenuation produced by the
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * cable. By reading the AGC registers, which represent the
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * combination of coarse and fine gain value, the value can be put
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * into a lookup table to obtain the approximate cable length
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * for each channel.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi **/
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchis32 e1000_get_cable_length_igp_2(struct e1000_hw *hw)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi{
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi struct e1000_phy_info *phy = &hw->phy;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi s32 ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi u16 phy_data, i, agc_value = 0;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi u16 cur_agc_index, max_agc_index = 0;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi u16 min_agc_index = IGP02E1000_CABLE_LENGTH_TABLE_SIZE - 1;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi static const u16 agc_reg_array[IGP02E1000_PHY_CHANNEL_NUM] = {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi IGP02E1000_PHY_AGC_A,
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi IGP02E1000_PHY_AGC_B,
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi IGP02E1000_PHY_AGC_C,
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi IGP02E1000_PHY_AGC_D
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi };
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGFUNC("e1000_get_cable_length_igp_2");
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* Read the AGC registers for all channels */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi for (i = 0; i < IGP02E1000_PHY_CHANNEL_NUM; i++) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = phy->ops.read_reg(hw, agc_reg_array[i], &phy_data);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (ret_val)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* Getting bits 15:9, which represent the combination of
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * coarse and fine gain values. The result is a number
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * that can be put into the lookup table to obtain the
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * approximate cable length.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi */
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi cur_agc_index = ((phy_data >> IGP02E1000_AGC_LENGTH_SHIFT) &
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi IGP02E1000_AGC_LENGTH_MASK);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* Array index bound check. */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if ((cur_agc_index >= IGP02E1000_CABLE_LENGTH_TABLE_SIZE) ||
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi (cur_agc_index == 0))
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return -E1000_ERR_PHY;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* Remove min & max AGC values from calculation. */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (e1000_igp_2_cable_length_table[min_agc_index] >
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi e1000_igp_2_cable_length_table[cur_agc_index])
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi min_agc_index = cur_agc_index;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (e1000_igp_2_cable_length_table[max_agc_index] <
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi e1000_igp_2_cable_length_table[cur_agc_index])
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi max_agc_index = cur_agc_index;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi agc_value += e1000_igp_2_cable_length_table[cur_agc_index];
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi agc_value -= (e1000_igp_2_cable_length_table[min_agc_index] +
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi e1000_igp_2_cable_length_table[max_agc_index]);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi agc_value /= (IGP02E1000_PHY_CHANNEL_NUM - 2);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* Calculate cable length with the error range of +/- 10 meters. */
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi phy->min_cable_length = (((agc_value - IGP02E1000_AGC_RANGE) > 0) ?
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi (agc_value - IGP02E1000_AGC_RANGE) : 0);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi phy->max_cable_length = agc_value + IGP02E1000_AGC_RANGE;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi phy->cable_length = (phy->min_cable_length + phy->max_cable_length) / 2;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return E1000_SUCCESS;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi}
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi/**
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * e1000_get_phy_info_m88 - Retrieve PHY information
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @hw: pointer to the HW structure
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi *
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * Valid for only copper links. Read the PHY status register (sticky read)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * to verify that link is up. Read the PHY special control register to
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * determine the polarity and 10base-T extended distance. Read the PHY
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * special status register to determine MDI/MDIx and current speed. If
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * speed is 1000, then determine cable length, local and remote receiver.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi **/
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchis32 e1000_get_phy_info_m88(struct e1000_hw *hw)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi{
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi struct e1000_phy_info *phy = &hw->phy;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi s32 ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi u16 phy_data;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi bool link;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGFUNC("e1000_get_phy_info_m88");
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (phy->media_type != e1000_media_type_copper) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGOUT("Phy info is only valid for copper media\n");
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return -E1000_ERR_CONFIG;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = e1000_phy_has_link_generic(hw, 1, 0, &link);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (ret_val)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (!link) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGOUT("Phy info is only valid if link is up\n");
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return -E1000_ERR_CONFIG;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = phy->ops.read_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (ret_val)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi phy->polarity_correction = !!(phy_data &
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi M88E1000_PSCR_POLARITY_REVERSAL);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = e1000_check_polarity_m88(hw);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (ret_val)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = phy->ops.read_reg(hw, M88E1000_PHY_SPEC_STATUS, &phy_data);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (ret_val)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi phy->is_mdix = !!(phy_data & M88E1000_PSSR_MDIX);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if ((phy_data & M88E1000_PSSR_SPEED) == M88E1000_PSSR_1000MBS) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = hw->phy.ops.get_cable_length(hw);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (ret_val)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = phy->ops.read_reg(hw, PHY_1000T_STATUS, &phy_data);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (ret_val)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi phy->local_rx = (phy_data & SR_1000T_LOCAL_RX_STATUS)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ? e1000_1000t_rx_status_ok
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi : e1000_1000t_rx_status_not_ok;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi phy->remote_rx = (phy_data & SR_1000T_REMOTE_RX_STATUS)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ? e1000_1000t_rx_status_ok
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi : e1000_1000t_rx_status_not_ok;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi } else {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* Set values to "undefined" */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi phy->cable_length = E1000_CABLE_LENGTH_UNDEFINED;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi phy->local_rx = e1000_1000t_rx_status_undefined;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi phy->remote_rx = e1000_1000t_rx_status_undefined;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi}
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi/**
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * e1000_get_phy_info_igp - Retrieve igp PHY information
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @hw: pointer to the HW structure
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi *
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * Read PHY status to determine if link is up. If link is up, then
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * set/determine 10base-T extended distance and polarity correction. Read
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * PHY port status to determine MDI/MDIx and speed. Based on the speed,
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * determine on the cable length, local and remote receiver.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi **/
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchis32 e1000_get_phy_info_igp(struct e1000_hw *hw)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi{
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi struct e1000_phy_info *phy = &hw->phy;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi s32 ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi u16 data;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi bool link;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGFUNC("e1000_get_phy_info_igp");
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = e1000_phy_has_link_generic(hw, 1, 0, &link);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (ret_val)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (!link) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGOUT("Phy info is only valid if link is up\n");
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return -E1000_ERR_CONFIG;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi phy->polarity_correction = TRUE;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = e1000_check_polarity_igp(hw);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (ret_val)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = phy->ops.read_reg(hw, IGP01E1000_PHY_PORT_STATUS, &data);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (ret_val)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi phy->is_mdix = !!(data & IGP01E1000_PSSR_MDIX);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if ((data & IGP01E1000_PSSR_SPEED_MASK) ==
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi IGP01E1000_PSSR_SPEED_1000MBPS) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = phy->ops.get_cable_length(hw);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (ret_val)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = phy->ops.read_reg(hw, PHY_1000T_STATUS, &data);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (ret_val)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi phy->local_rx = (data & SR_1000T_LOCAL_RX_STATUS)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ? e1000_1000t_rx_status_ok
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi : e1000_1000t_rx_status_not_ok;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi phy->remote_rx = (data & SR_1000T_REMOTE_RX_STATUS)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ? e1000_1000t_rx_status_ok
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi : e1000_1000t_rx_status_not_ok;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi } else {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi phy->cable_length = E1000_CABLE_LENGTH_UNDEFINED;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi phy->local_rx = e1000_1000t_rx_status_undefined;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi phy->remote_rx = e1000_1000t_rx_status_undefined;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi}
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi/**
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * e1000_get_phy_info_ife - Retrieves various IFE PHY states
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @hw: pointer to the HW structure
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi *
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * Populates "phy" structure with various feature states.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi **/
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchis32 e1000_get_phy_info_ife(struct e1000_hw *hw)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi{
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi struct e1000_phy_info *phy = &hw->phy;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi s32 ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi u16 data;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi bool link;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGFUNC("e1000_get_phy_info_ife");
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = e1000_phy_has_link_generic(hw, 1, 0, &link);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (ret_val)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (!link) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGOUT("Phy info is only valid if link is up\n");
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return -E1000_ERR_CONFIG;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = phy->ops.read_reg(hw, IFE_PHY_SPECIAL_CONTROL, &data);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (ret_val)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi phy->polarity_correction = !(data & IFE_PSC_AUTO_POLARITY_DISABLE);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (phy->polarity_correction) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = e1000_check_polarity_ife(hw);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (ret_val)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi } else {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* Polarity is forced */
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi phy->cable_polarity = ((data & IFE_PSC_FORCE_POLARITY)
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi ? e1000_rev_polarity_reversed
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi : e1000_rev_polarity_normal);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = phy->ops.read_reg(hw, IFE_PHY_MDIX_CONTROL, &data);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (ret_val)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi phy->is_mdix = !!(data & IFE_PMC_MDIX_STATUS);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* The following parameters are undefined for 10/100 operation. */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi phy->cable_length = E1000_CABLE_LENGTH_UNDEFINED;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi phy->local_rx = e1000_1000t_rx_status_undefined;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi phy->remote_rx = e1000_1000t_rx_status_undefined;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return E1000_SUCCESS;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi}
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi/**
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * e1000_phy_sw_reset_generic - PHY software reset
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @hw: pointer to the HW structure
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi *
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * Does a software reset of the PHY by reading the PHY control register and
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * setting/write the control register reset bit to the PHY.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi **/
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchis32 e1000_phy_sw_reset_generic(struct e1000_hw *hw)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi{
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi s32 ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi u16 phy_ctrl;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGFUNC("e1000_phy_sw_reset_generic");
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (!hw->phy.ops.read_reg)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return E1000_SUCCESS;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = hw->phy.ops.read_reg(hw, PHY_CONTROL, &phy_ctrl);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (ret_val)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi phy_ctrl |= MII_CR_RESET;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = hw->phy.ops.write_reg(hw, PHY_CONTROL, phy_ctrl);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (ret_val)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi usec_delay(1);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi}
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi/**
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * e1000_phy_hw_reset_generic - PHY hardware reset
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @hw: pointer to the HW structure
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi *
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * Verify the reset block is not blocking us from resetting. Acquire
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * semaphore (if necessary) and read/set/write the device control reset
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * bit in the PHY. Wait the appropriate delay time for the device to
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * reset and release the semaphore (if necessary).
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi **/
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchis32 e1000_phy_hw_reset_generic(struct e1000_hw *hw)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi{
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi struct e1000_phy_info *phy = &hw->phy;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi s32 ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi u32 ctrl;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGFUNC("e1000_phy_hw_reset_generic");
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (phy->ops.check_reset_block) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = phy->ops.check_reset_block(hw);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (ret_val)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return E1000_SUCCESS;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = phy->ops.acquire(hw);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (ret_val)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ctrl = E1000_READ_REG(hw, E1000_CTRL);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi E1000_WRITE_REG(hw, E1000_CTRL, ctrl | E1000_CTRL_PHY_RST);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi E1000_WRITE_FLUSH(hw);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi usec_delay(phy->reset_delay_us);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi E1000_WRITE_REG(hw, E1000_CTRL, ctrl);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi E1000_WRITE_FLUSH(hw);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi usec_delay(150);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi phy->ops.release(hw);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return phy->ops.get_cfg_done(hw);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi}
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi/**
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * e1000_get_cfg_done_generic - Generic configuration done
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @hw: pointer to the HW structure
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi *
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * Generic function to wait 10 milli-seconds for configuration to complete
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * and return success.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi **/
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchis32 e1000_get_cfg_done_generic(struct e1000_hw E1000_UNUSEDARG *hw)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi{
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGFUNC("e1000_get_cfg_done_generic");
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi msec_delay_irq(10);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return E1000_SUCCESS;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi}
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi/**
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * e1000_phy_init_script_igp3 - Inits the IGP3 PHY
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @hw: pointer to the HW structure
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi *
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * Initializes a Intel Gigabit PHY3 when an EEPROM is not present.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi **/
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchis32 e1000_phy_init_script_igp3(struct e1000_hw *hw)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi{
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGOUT("Running IGP 3 PHY init script\n");
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* PHY init IGP 3 */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* Enable rise/fall, 10-mode work in class-A */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi hw->phy.ops.write_reg(hw, 0x2F5B, 0x9018);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* Remove all caps from Replica path filter */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi hw->phy.ops.write_reg(hw, 0x2F52, 0x0000);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* Bias trimming for ADC, AFE and Driver (Default) */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi hw->phy.ops.write_reg(hw, 0x2FB1, 0x8B24);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* Increase Hybrid poly bias */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi hw->phy.ops.write_reg(hw, 0x2FB2, 0xF8F0);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* Add 4% to Tx amplitude in Gig mode */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi hw->phy.ops.write_reg(hw, 0x2010, 0x10B0);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* Disable trimming (TTT) */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi hw->phy.ops.write_reg(hw, 0x2011, 0x0000);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* Poly DC correction to 94.6% + 2% for all channels */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi hw->phy.ops.write_reg(hw, 0x20DD, 0x249A);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* ABS DC correction to 95.9% */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi hw->phy.ops.write_reg(hw, 0x20DE, 0x00D3);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* BG temp curve trim */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi hw->phy.ops.write_reg(hw, 0x28B4, 0x04CE);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* Increasing ADC OPAMP stage 1 currents to max */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi hw->phy.ops.write_reg(hw, 0x2F70, 0x29E4);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* Force 1000 ( required for enabling PHY regs configuration) */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi hw->phy.ops.write_reg(hw, 0x0000, 0x0140);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* Set upd_freq to 6 */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi hw->phy.ops.write_reg(hw, 0x1F30, 0x1606);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* Disable NPDFE */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi hw->phy.ops.write_reg(hw, 0x1F31, 0xB814);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* Disable adaptive fixed FFE (Default) */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi hw->phy.ops.write_reg(hw, 0x1F35, 0x002A);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* Enable FFE hysteresis */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi hw->phy.ops.write_reg(hw, 0x1F3E, 0x0067);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* Fixed FFE for short cable lengths */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi hw->phy.ops.write_reg(hw, 0x1F54, 0x0065);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* Fixed FFE for medium cable lengths */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi hw->phy.ops.write_reg(hw, 0x1F55, 0x002A);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* Fixed FFE for long cable lengths */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi hw->phy.ops.write_reg(hw, 0x1F56, 0x002A);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* Enable Adaptive Clip Threshold */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi hw->phy.ops.write_reg(hw, 0x1F72, 0x3FB0);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* AHT reset limit to 1 */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi hw->phy.ops.write_reg(hw, 0x1F76, 0xC0FF);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* Set AHT master delay to 127 msec */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi hw->phy.ops.write_reg(hw, 0x1F77, 0x1DEC);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* Set scan bits for AHT */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi hw->phy.ops.write_reg(hw, 0x1F78, 0xF9EF);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* Set AHT Preset bits */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi hw->phy.ops.write_reg(hw, 0x1F79, 0x0210);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* Change integ_factor of channel A to 3 */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi hw->phy.ops.write_reg(hw, 0x1895, 0x0003);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* Change prop_factor of channels BCD to 8 */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi hw->phy.ops.write_reg(hw, 0x1796, 0x0008);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* Change cg_icount + enable integbp for channels BCD */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi hw->phy.ops.write_reg(hw, 0x1798, 0xD008);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* Change cg_icount + enable integbp + change prop_factor_master
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * to 8 for channel A
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi hw->phy.ops.write_reg(hw, 0x1898, 0xD918);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* Disable AHT in Slave mode on channel A */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi hw->phy.ops.write_reg(hw, 0x187A, 0x0800);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* Enable LPLU and disable AN to 1000 in non-D0a states,
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * Enable SPD+B2B
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi hw->phy.ops.write_reg(hw, 0x0019, 0x008D);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* Enable restart AN on an1000_dis change */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi hw->phy.ops.write_reg(hw, 0x001B, 0x2080);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* Enable wh_fifo read clock in 10/100 modes */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi hw->phy.ops.write_reg(hw, 0x0014, 0x0045);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* Restart AN, Speed selection is 1000 */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi hw->phy.ops.write_reg(hw, 0x0000, 0x1340);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return E1000_SUCCESS;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi}
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi/**
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * e1000_get_phy_type_from_id - Get PHY type from id
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @phy_id: phy_id read from the phy
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi *
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * Returns the phy type from the id.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi **/
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchienum e1000_phy_type e1000_get_phy_type_from_id(u32 phy_id)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi{
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi enum e1000_phy_type phy_type = e1000_phy_unknown;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi switch (phy_id) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi case M88E1000_I_PHY_ID:
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi case M88E1000_E_PHY_ID:
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi case M88E1111_I_PHY_ID:
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi case M88E1011_I_PHY_ID:
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi case M88E1543_E_PHY_ID:
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi case M88E1512_E_PHY_ID:
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi case I347AT4_E_PHY_ID:
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi case M88E1112_E_PHY_ID:
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi case M88E1340M_E_PHY_ID:
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi phy_type = e1000_phy_m88;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi break;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi case IGP01E1000_I_PHY_ID: /* IGP 1 & 2 share this */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi phy_type = e1000_phy_igp_2;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi break;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi case GG82563_E_PHY_ID:
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi phy_type = e1000_phy_gg82563;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi break;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi case IGP03E1000_E_PHY_ID:
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi phy_type = e1000_phy_igp_3;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi break;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi case IFE_E_PHY_ID:
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi case IFE_PLUS_E_PHY_ID:
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi case IFE_C_E_PHY_ID:
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi phy_type = e1000_phy_ife;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi break;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi case BME1000_E_PHY_ID:
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi case BME1000_E_PHY_ID_R2:
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi phy_type = e1000_phy_bm;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi break;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi case I82578_E_PHY_ID:
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi phy_type = e1000_phy_82578;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi break;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi case I82577_E_PHY_ID:
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi phy_type = e1000_phy_82577;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi break;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi case I82579_E_PHY_ID:
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi phy_type = e1000_phy_82579;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi break;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi case I217_E_PHY_ID:
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi phy_type = e1000_phy_i217;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi break;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi case I82580_I_PHY_ID:
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi phy_type = e1000_phy_82580;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi break;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi case I210_I_PHY_ID:
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi phy_type = e1000_phy_i210;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi break;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi default:
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi phy_type = e1000_phy_unknown;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi break;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return phy_type;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi}
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi/**
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * e1000_determine_phy_address - Determines PHY address.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @hw: pointer to the HW structure
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi *
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * This uses a trial and error method to loop through possible PHY
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * addresses. It tests each by reading the PHY ID registers and
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * checking for a match.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi **/
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchis32 e1000_determine_phy_address(struct e1000_hw *hw)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi{
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi u32 phy_addr = 0;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi u32 i;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi enum e1000_phy_type phy_type = e1000_phy_unknown;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi hw->phy.id = phy_type;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi for (phy_addr = 0; phy_addr < E1000_MAX_PHY_ADDR; phy_addr++) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi hw->phy.addr = phy_addr;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi i = 0;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi do {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi e1000_get_phy_id(hw);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi phy_type = e1000_get_phy_type_from_id(hw->phy.id);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* If phy_type is valid, break - we found our
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * PHY address
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (phy_type != e1000_phy_unknown)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return E1000_SUCCESS;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi msec_delay(1);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi i++;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi } while (i < 10);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return -E1000_ERR_PHY_TYPE;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi}
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi/**
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * e1000_get_phy_addr_for_bm_page - Retrieve PHY page address
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @page: page to access
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi *
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * Returns the phy address for the page requested.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi **/
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchistatic u32 e1000_get_phy_addr_for_bm_page(u32 page, u32 reg)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi{
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi u32 phy_addr = 2;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if ((page >= 768) || (page == 0 && reg == 25) || (reg == 31))
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi phy_addr = 1;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return phy_addr;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi}
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi/**
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * e1000_write_phy_reg_bm - Write BM PHY register
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @hw: pointer to the HW structure
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @offset: register offset to write to
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @data: data to write at register offset
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi *
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * Acquires semaphore, if necessary, then writes the data to PHY register
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * at the offset. Release any acquired semaphores before exiting.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi **/
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchis32 e1000_write_phy_reg_bm(struct e1000_hw *hw, u32 offset, u16 data)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi{
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi s32 ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi u32 page = offset >> IGP_PAGE_SHIFT;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGFUNC("e1000_write_phy_reg_bm");
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = hw->phy.ops.acquire(hw);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (ret_val)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* Page 800 works differently than the rest so it has its own func */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (page == BM_WUC_PAGE) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = e1000_access_phy_wakeup_reg_bm(hw, offset, &data,
49b7860084dbba18bc00b29413d6182197f9fe93Robert Mustacchi FALSE, false);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi goto release;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi hw->phy.addr = e1000_get_phy_addr_for_bm_page(page, offset);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (offset > MAX_PHY_MULTI_PAGE_REG) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi u32 page_shift, page_select;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* Page select is register 31 for phy address 1 and 22 for
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * phy address 2 and 3. Page select is shifted only for
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * phy address 1.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (hw->phy.addr == 1) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi page_shift = IGP_PAGE_SHIFT;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi page_select = IGP01E1000_PHY_PAGE_SELECT;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi } else {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi page_shift = 0;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi page_select = BM_PHY_PAGE_SELECT;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* Page is shifted left, PHY expects (page x 32) */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = e1000_write_phy_reg_mdic(hw, page_select,
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi (page << page_shift));
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (ret_val)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi goto release;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = e1000_write_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset,
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi data);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchirelease:
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi hw->phy.ops.release(hw);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi}
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi/**
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * e1000_read_phy_reg_bm - Read BM PHY register
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @hw: pointer to the HW structure
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @offset: register offset to be read
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @data: pointer to the read data
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi *
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * Acquires semaphore, if necessary, then reads the PHY register at offset
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * and storing the retrieved information in data. Release any acquired
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * semaphores before exiting.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi **/
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchis32 e1000_read_phy_reg_bm(struct e1000_hw *hw, u32 offset, u16 *data)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi{
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi s32 ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi u32 page = offset >> IGP_PAGE_SHIFT;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGFUNC("e1000_read_phy_reg_bm");
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = hw->phy.ops.acquire(hw);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (ret_val)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* Page 800 works differently than the rest so it has its own func */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (page == BM_WUC_PAGE) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = e1000_access_phy_wakeup_reg_bm(hw, offset, data,
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi TRUE, FALSE);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi goto release;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi hw->phy.addr = e1000_get_phy_addr_for_bm_page(page, offset);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (offset > MAX_PHY_MULTI_PAGE_REG) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi u32 page_shift, page_select;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* Page select is register 31 for phy address 1 and 22 for
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * phy address 2 and 3. Page select is shifted only for
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * phy address 1.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (hw->phy.addr == 1) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi page_shift = IGP_PAGE_SHIFT;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi page_select = IGP01E1000_PHY_PAGE_SELECT;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi } else {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi page_shift = 0;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi page_select = BM_PHY_PAGE_SELECT;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* Page is shifted left, PHY expects (page x 32) */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = e1000_write_phy_reg_mdic(hw, page_select,
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi (page << page_shift));
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (ret_val)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi goto release;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = e1000_read_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset,
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi data);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchirelease:
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi hw->phy.ops.release(hw);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi}
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi/**
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * e1000_read_phy_reg_bm2 - Read BM PHY register
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @hw: pointer to the HW structure
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @offset: register offset to be read
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @data: pointer to the read data
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi *
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * Acquires semaphore, if necessary, then reads the PHY register at offset
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * and storing the retrieved information in data. Release any acquired
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * semaphores before exiting.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi **/
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchis32 e1000_read_phy_reg_bm2(struct e1000_hw *hw, u32 offset, u16 *data)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi{
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi s32 ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi u16 page = (u16)(offset >> IGP_PAGE_SHIFT);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGFUNC("e1000_read_phy_reg_bm2");
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = hw->phy.ops.acquire(hw);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (ret_val)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* Page 800 works differently than the rest so it has its own func */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (page == BM_WUC_PAGE) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = e1000_access_phy_wakeup_reg_bm(hw, offset, data,
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi TRUE, FALSE);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi goto release;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi hw->phy.addr = 1;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (offset > MAX_PHY_MULTI_PAGE_REG) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* Page is shifted left, PHY expects (page x 32) */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = e1000_write_phy_reg_mdic(hw, BM_PHY_PAGE_SELECT,
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi page);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (ret_val)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi goto release;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = e1000_read_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset,
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi data);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchirelease:
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi hw->phy.ops.release(hw);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi}
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi/**
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * e1000_write_phy_reg_bm2 - Write BM PHY register
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @hw: pointer to the HW structure
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @offset: register offset to write to
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @data: data to write at register offset
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi *
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * Acquires semaphore, if necessary, then writes the data to PHY register
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * at the offset. Release any acquired semaphores before exiting.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi **/
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchis32 e1000_write_phy_reg_bm2(struct e1000_hw *hw, u32 offset, u16 data)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi{
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi s32 ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi u16 page = (u16)(offset >> IGP_PAGE_SHIFT);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGFUNC("e1000_write_phy_reg_bm2");
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = hw->phy.ops.acquire(hw);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (ret_val)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* Page 800 works differently than the rest so it has its own func */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (page == BM_WUC_PAGE) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = e1000_access_phy_wakeup_reg_bm(hw, offset, &data,
49b7860084dbba18bc00b29413d6182197f9fe93Robert Mustacchi FALSE, false);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi goto release;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi hw->phy.addr = 1;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (offset > MAX_PHY_MULTI_PAGE_REG) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* Page is shifted left, PHY expects (page x 32) */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = e1000_write_phy_reg_mdic(hw, BM_PHY_PAGE_SELECT,
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi page);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (ret_val)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi goto release;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = e1000_write_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset,
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi data);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchirelease:
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi hw->phy.ops.release(hw);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi}
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi/**
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * e1000_enable_phy_wakeup_reg_access_bm - enable access to BM wakeup registers
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @hw: pointer to the HW structure
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @phy_reg: pointer to store original contents of BM_WUC_ENABLE_REG
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi *
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * Assumes semaphore already acquired and phy_reg points to a valid memory
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * address to store contents of the BM_WUC_ENABLE_REG register.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi **/
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchis32 e1000_enable_phy_wakeup_reg_access_bm(struct e1000_hw *hw, u16 *phy_reg)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi{
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi s32 ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi u16 temp;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGFUNC("e1000_enable_phy_wakeup_reg_access_bm");
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (!phy_reg)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return -E1000_ERR_PARAM;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* All page select, port ctrl and wakeup registers use phy address 1 */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi hw->phy.addr = 1;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* Select Port Control Registers page */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = e1000_set_page_igp(hw, (BM_PORT_CTRL_PAGE << IGP_PAGE_SHIFT));
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (ret_val) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGOUT("Could not set Port Control page\n");
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = e1000_read_phy_reg_mdic(hw, BM_WUC_ENABLE_REG, phy_reg);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (ret_val) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGOUT2("Could not read PHY register %d.%d\n",
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi BM_PORT_CTRL_PAGE, BM_WUC_ENABLE_REG);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* Enable both PHY wakeup mode and Wakeup register page writes.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * Prevent a power state change by disabling ME and Host PHY wakeup.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi temp = *phy_reg;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi temp |= BM_WUC_ENABLE_BIT;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi temp &= ~(BM_WUC_ME_WU_BIT | BM_WUC_HOST_WU_BIT);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = e1000_write_phy_reg_mdic(hw, BM_WUC_ENABLE_REG, temp);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (ret_val) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGOUT2("Could not write PHY register %d.%d\n",
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi BM_PORT_CTRL_PAGE, BM_WUC_ENABLE_REG);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* Select Host Wakeup Registers page - caller now able to write
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * registers on the Wakeup registers page
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return e1000_set_page_igp(hw, (BM_WUC_PAGE << IGP_PAGE_SHIFT));
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi}
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi/**
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * e1000_disable_phy_wakeup_reg_access_bm - disable access to BM wakeup regs
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @hw: pointer to the HW structure
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @phy_reg: pointer to original contents of BM_WUC_ENABLE_REG
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi *
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * Restore BM_WUC_ENABLE_REG to its original value.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi *
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * Assumes semaphore already acquired and *phy_reg is the contents of the
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * BM_WUC_ENABLE_REG before register(s) on BM_WUC_PAGE were accessed by
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * caller.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi **/
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchis32 e1000_disable_phy_wakeup_reg_access_bm(struct e1000_hw *hw, u16 *phy_reg)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi{
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi s32 ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGFUNC("e1000_disable_phy_wakeup_reg_access_bm");
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (!phy_reg)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return -E1000_ERR_PARAM;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* Select Port Control Registers page */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = e1000_set_page_igp(hw, (BM_PORT_CTRL_PAGE << IGP_PAGE_SHIFT));
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (ret_val) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGOUT("Could not set Port Control page\n");
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* Restore 769.17 to its original value */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = e1000_write_phy_reg_mdic(hw, BM_WUC_ENABLE_REG, *phy_reg);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (ret_val)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGOUT2("Could not restore PHY register %d.%d\n",
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi BM_PORT_CTRL_PAGE, BM_WUC_ENABLE_REG);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi}
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi/**
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * e1000_access_phy_wakeup_reg_bm - Read/write BM PHY wakeup register
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @hw: pointer to the HW structure
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @offset: register offset to be read or written
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @data: pointer to the data to read or write
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @read: determines if operation is read or write
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @page_set: BM_WUC_PAGE already set and access enabled
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi *
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * Read the PHY register at offset and store the retrieved information in
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * data, or write data to PHY register at offset. Note the procedure to
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * access the PHY wakeup registers is different than reading the other PHY
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * registers. It works as such:
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * 1) Set 769.17.2 (page 769, register 17, bit 2) = 1
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * 2) Set page to 800 for host (801 if we were manageability)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * 3) Write the address using the address opcode (0x11)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * 4) Read or write the data using the data opcode (0x12)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * 5) Restore 769.17.2 to its original value
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi *
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * Steps 1 and 2 are done by e1000_enable_phy_wakeup_reg_access_bm() and
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * step 5 is done by e1000_disable_phy_wakeup_reg_access_bm().
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi *
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * Assumes semaphore is already acquired. When page_set==TRUE, assumes
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * the PHY page is set to BM_WUC_PAGE (i.e. a function in the call stack
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * is responsible for calls to e1000_[enable|disable]_phy_wakeup_reg_bm()).
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi **/
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchistatic s32 e1000_access_phy_wakeup_reg_bm(struct e1000_hw *hw, u32 offset,
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi u16 *data, bool read, bool page_set)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi{
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi s32 ret_val;
49b7860084dbba18bc00b29413d6182197f9fe93Robert Mustacchi u16 reg = BM_PHY_REG_NUM(offset);
49b7860084dbba18bc00b29413d6182197f9fe93Robert Mustacchi u16 page = BM_PHY_REG_PAGE(offset);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi u16 phy_reg = 0;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGFUNC("e1000_access_phy_wakeup_reg_bm");
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* Gig must be disabled for MDIO accesses to Host Wakeup reg page */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if ((hw->mac.type == e1000_pchlan) &&
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi (!(E1000_READ_REG(hw, E1000_PHY_CTRL) & E1000_PHY_CTRL_GBE_DISABLE)))
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGOUT1("Attempting to access page %d while gig enabled.\n",
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi page);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (!page_set) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* Enable access to PHY wakeup registers */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = e1000_enable_phy_wakeup_reg_access_bm(hw, &phy_reg);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (ret_val) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGOUT("Could not enable PHY wakeup reg access\n");
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGOUT2("Accessing PHY page %d reg 0x%x\n", page, reg);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* Write the Wakeup register page offset value using opcode 0x11 */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = e1000_write_phy_reg_mdic(hw, BM_WUC_ADDRESS_OPCODE, reg);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (ret_val) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGOUT1("Could not write address opcode to page %d\n", page);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (read) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* Read the Wakeup register page value using opcode 0x12 */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = e1000_read_phy_reg_mdic(hw, BM_WUC_DATA_OPCODE,
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi data);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi } else {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* Write the Wakeup register page value using opcode 0x12 */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = e1000_write_phy_reg_mdic(hw, BM_WUC_DATA_OPCODE,
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi *data);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (ret_val) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGOUT2("Could not access PHY reg %d.%d\n", page, reg);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (!page_set)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = e1000_disable_phy_wakeup_reg_access_bm(hw, &phy_reg);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi}
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi/**
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * e1000_power_up_phy_copper - Restore copper link in case of PHY power down
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @hw: pointer to the HW structure
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi *
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * In the case of a PHY power down to save power, or to turn off link during a
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * driver unload, or wake on lan is not enabled, restore the link to previous
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * settings.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi **/
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchivoid e1000_power_up_phy_copper(struct e1000_hw *hw)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi{
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi u16 mii_reg = 0;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* The PHY will retain its settings across a power down/up cycle */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi hw->phy.ops.read_reg(hw, PHY_CONTROL, &mii_reg);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi mii_reg &= ~MII_CR_POWER_DOWN;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi hw->phy.ops.write_reg(hw, PHY_CONTROL, mii_reg);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi}
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi/**
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * e1000_power_down_phy_copper - Restore copper link in case of PHY power down
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @hw: pointer to the HW structure
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi *
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * In the case of a PHY power down to save power, or to turn off link during a
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * driver unload, or wake on lan is not enabled, restore the link to previous
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * settings.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi **/
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchivoid e1000_power_down_phy_copper(struct e1000_hw *hw)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi{
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi u16 mii_reg = 0;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* The PHY will retain its settings across a power down/up cycle */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi hw->phy.ops.read_reg(hw, PHY_CONTROL, &mii_reg);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi mii_reg |= MII_CR_POWER_DOWN;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi hw->phy.ops.write_reg(hw, PHY_CONTROL, mii_reg);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi msec_delay(1);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi}
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi/**
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * __e1000_read_phy_reg_hv - Read HV PHY register
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @hw: pointer to the HW structure
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @offset: register offset to be read
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @data: pointer to the read data
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @locked: semaphore has already been acquired or not
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi *
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * Acquires semaphore, if necessary, then reads the PHY register at offset
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * and stores the retrieved information in data. Release any acquired
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * semaphore before exiting.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi **/
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchistatic s32 __e1000_read_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 *data,
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi bool locked, bool page_set)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi{
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi s32 ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi u16 page = BM_PHY_REG_PAGE(offset);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi u16 reg = BM_PHY_REG_NUM(offset);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi u32 phy_addr = hw->phy.addr = e1000_get_phy_addr_for_hv_page(page);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGFUNC("__e1000_read_phy_reg_hv");
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (!locked) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = hw->phy.ops.acquire(hw);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (ret_val)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* Page 800 works differently than the rest so it has its own func */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (page == BM_WUC_PAGE) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = e1000_access_phy_wakeup_reg_bm(hw, offset, data,
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi TRUE, page_set);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi goto out;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (page > 0 && page < HV_INTC_FC_PAGE_START) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = e1000_access_phy_debug_regs_hv(hw, offset,
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi data, TRUE);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi goto out;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (!page_set) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (page == HV_INTC_FC_PAGE_START)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi page = 0;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (reg > MAX_PHY_MULTI_PAGE_REG) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* Page is shifted left, PHY expects (page x 32) */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = e1000_set_page_igp(hw,
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi (page << IGP_PAGE_SHIFT));
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi hw->phy.addr = phy_addr;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (ret_val)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi goto out;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGOUT3("reading PHY page %d (or 0x%x shifted) reg 0x%x\n", page,
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi page << IGP_PAGE_SHIFT, reg);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = e1000_read_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & reg,
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi data);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchiout:
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (!locked)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi hw->phy.ops.release(hw);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi}
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi/**
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * e1000_read_phy_reg_hv - Read HV PHY register
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @hw: pointer to the HW structure
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @offset: register offset to be read
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @data: pointer to the read data
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi *
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * Acquires semaphore then reads the PHY register at offset and stores
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * the retrieved information in data. Release the acquired semaphore
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * before exiting.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi **/
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchis32 e1000_read_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 *data)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi{
49b7860084dbba18bc00b29413d6182197f9fe93Robert Mustacchi return __e1000_read_phy_reg_hv(hw, offset, data, FALSE, false);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi}
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi/**
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * e1000_read_phy_reg_hv_locked - Read HV PHY register
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @hw: pointer to the HW structure
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @offset: register offset to be read
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @data: pointer to the read data
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi *
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * Reads the PHY register at offset and stores the retrieved information
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * in data. Assumes semaphore already acquired.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi **/
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchis32 e1000_read_phy_reg_hv_locked(struct e1000_hw *hw, u32 offset, u16 *data)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi{
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return __e1000_read_phy_reg_hv(hw, offset, data, TRUE, FALSE);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi}
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi/**
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * e1000_read_phy_reg_page_hv - Read HV PHY register
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @hw: pointer to the HW structure
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @offset: register offset to write to
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @data: data to write at register offset
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi *
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * Reads the PHY register at offset and stores the retrieved information
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * in data. Assumes semaphore already acquired and page already set.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi **/
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchis32 e1000_read_phy_reg_page_hv(struct e1000_hw *hw, u32 offset, u16 *data)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi{
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return __e1000_read_phy_reg_hv(hw, offset, data, TRUE, true);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi}
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi/**
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * __e1000_write_phy_reg_hv - Write HV PHY register
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @hw: pointer to the HW structure
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @offset: register offset to write to
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @data: data to write at register offset
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @locked: semaphore has already been acquired or not
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi *
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * Acquires semaphore, if necessary, then writes the data to PHY register
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * at the offset. Release any acquired semaphores before exiting.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi **/
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchistatic s32 __e1000_write_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 data,
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi bool locked, bool page_set)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi{
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi s32 ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi u16 page = BM_PHY_REG_PAGE(offset);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi u16 reg = BM_PHY_REG_NUM(offset);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi u32 phy_addr = hw->phy.addr = e1000_get_phy_addr_for_hv_page(page);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGFUNC("__e1000_write_phy_reg_hv");
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (!locked) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = hw->phy.ops.acquire(hw);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (ret_val)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* Page 800 works differently than the rest so it has its own func */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (page == BM_WUC_PAGE) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = e1000_access_phy_wakeup_reg_bm(hw, offset, &data,
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi FALSE, page_set);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi goto out;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (page > 0 && page < HV_INTC_FC_PAGE_START) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = e1000_access_phy_debug_regs_hv(hw, offset,
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi &data, FALSE);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi goto out;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (!page_set) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (page == HV_INTC_FC_PAGE_START)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi page = 0;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* Workaround MDIO accesses being disabled after entering IEEE
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * Power Down (when bit 11 of the PHY Control register is set)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if ((hw->phy.type == e1000_phy_82578) &&
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi (hw->phy.revision >= 1) &&
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi (hw->phy.addr == 2) &&
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi !(MAX_PHY_REG_ADDRESS & reg) &&
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi (data & (1 << 11))) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi u16 data2 = 0x7EFF;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = e1000_access_phy_debug_regs_hv(hw,
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi (1 << 6) | 0x3,
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi &data2, FALSE);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (ret_val)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi goto out;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (reg > MAX_PHY_MULTI_PAGE_REG) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* Page is shifted left, PHY expects (page x 32) */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = e1000_set_page_igp(hw,
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi (page << IGP_PAGE_SHIFT));
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi hw->phy.addr = phy_addr;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (ret_val)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi goto out;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGOUT3("writing PHY page %d (or 0x%x shifted) reg 0x%x\n", page,
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi page << IGP_PAGE_SHIFT, reg);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = e1000_write_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & reg,
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi data);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchiout:
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (!locked)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi hw->phy.ops.release(hw);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi}
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi/**
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * e1000_write_phy_reg_hv - Write HV PHY register
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @hw: pointer to the HW structure
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @offset: register offset to write to
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @data: data to write at register offset
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi *
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * Acquires semaphore then writes the data to PHY register at the offset.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * Release the acquired semaphores before exiting.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi **/
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchis32 e1000_write_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 data)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi{
49b7860084dbba18bc00b29413d6182197f9fe93Robert Mustacchi return __e1000_write_phy_reg_hv(hw, offset, data, FALSE, false);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi}
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi/**
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * e1000_write_phy_reg_hv_locked - Write HV PHY register
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @hw: pointer to the HW structure
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @offset: register offset to write to
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @data: data to write at register offset
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi *
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * Writes the data to PHY register at the offset. Assumes semaphore
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * already acquired.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi **/
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchis32 e1000_write_phy_reg_hv_locked(struct e1000_hw *hw, u32 offset, u16 data)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi{
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return __e1000_write_phy_reg_hv(hw, offset, data, TRUE, FALSE);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi}
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi/**
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * e1000_write_phy_reg_page_hv - Write HV PHY register
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @hw: pointer to the HW structure
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @offset: register offset to write to
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @data: data to write at register offset
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi *
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * Writes the data to PHY register at the offset. Assumes semaphore
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * already acquired and page already set.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi **/
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchis32 e1000_write_phy_reg_page_hv(struct e1000_hw *hw, u32 offset, u16 data)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi{
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return __e1000_write_phy_reg_hv(hw, offset, data, TRUE, true);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi}
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi/**
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * e1000_get_phy_addr_for_hv_page - Get PHY adrress based on page
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @page: page to be accessed
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi **/
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchistatic u32 e1000_get_phy_addr_for_hv_page(u32 page)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi{
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi u32 phy_addr = 2;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (page >= HV_INTC_FC_PAGE_START)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi phy_addr = 1;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return phy_addr;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi}
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi/**
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * e1000_access_phy_debug_regs_hv - Read HV PHY vendor specific high registers
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @hw: pointer to the HW structure
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @offset: register offset to be read or written
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @data: pointer to the data to be read or written
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @read: determines if operation is read or write
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi *
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * Reads the PHY register at offset and stores the retreived information
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * in data. Assumes semaphore already acquired. Note that the procedure
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * to access these regs uses the address port and data port to read/write.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * These accesses done with PHY address 2 and without using pages.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi **/
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchistatic s32 e1000_access_phy_debug_regs_hv(struct e1000_hw *hw, u32 offset,
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi u16 *data, bool read)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi{
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi s32 ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi u32 addr_reg;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi u32 data_reg;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGFUNC("e1000_access_phy_debug_regs_hv");
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* This takes care of the difference with desktop vs mobile phy */
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi addr_reg = ((hw->phy.type == e1000_phy_82578) ?
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi I82578_ADDR_REG : I82577_ADDR_REG);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi data_reg = addr_reg + 1;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* All operations in this function are phy address 2 */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi hw->phy.addr = 2;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* masking with 0x3F to remove the page from offset */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = e1000_write_phy_reg_mdic(hw, addr_reg, (u16)offset & 0x3F);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (ret_val) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGOUT("Could not write the Address Offset port register\n");
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* Read or write the data value next */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (read)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = e1000_read_phy_reg_mdic(hw, data_reg, data);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi else
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = e1000_write_phy_reg_mdic(hw, data_reg, *data);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (ret_val)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGOUT("Could not access the Data port register\n");
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi}
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi/**
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * e1000_link_stall_workaround_hv - Si workaround
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @hw: pointer to the HW structure
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi *
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * This function works around a Si bug where the link partner can get
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * a link up indication before the PHY does. If small packets are sent
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * by the link partner they can be placed in the packet buffer without
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * being properly accounted for by the PHY and will stall preventing
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * further packets from being received. The workaround is to clear the
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * packet buffer after the PHY detects link up.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi **/
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchis32 e1000_link_stall_workaround_hv(struct e1000_hw *hw)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi{
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi s32 ret_val = E1000_SUCCESS;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi u16 data;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGFUNC("e1000_link_stall_workaround_hv");
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (hw->phy.type != e1000_phy_82578)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return E1000_SUCCESS;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* Do not apply workaround if in PHY loopback bit 14 set */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi hw->phy.ops.read_reg(hw, PHY_CONTROL, &data);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (data & PHY_CONTROL_LB)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return E1000_SUCCESS;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* check if link is up and at 1Gbps */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = hw->phy.ops.read_reg(hw, BM_CS_STATUS, &data);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (ret_val)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi data &= (BM_CS_STATUS_LINK_UP | BM_CS_STATUS_RESOLVED |
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi BM_CS_STATUS_SPEED_MASK);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (data != (BM_CS_STATUS_LINK_UP | BM_CS_STATUS_RESOLVED |
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi BM_CS_STATUS_SPEED_1000))
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return E1000_SUCCESS;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi msec_delay(200);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* flush the packets in the fifo buffer */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = hw->phy.ops.write_reg(hw, HV_MUX_DATA_CTRL,
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi (HV_MUX_DATA_CTRL_GEN_TO_MAC |
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi HV_MUX_DATA_CTRL_FORCE_SPEED));
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (ret_val)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return hw->phy.ops.write_reg(hw, HV_MUX_DATA_CTRL,
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi HV_MUX_DATA_CTRL_GEN_TO_MAC);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi}
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi/**
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * e1000_check_polarity_82577 - Checks the polarity.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @hw: pointer to the HW structure
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi *
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * Success returns 0, Failure returns -E1000_ERR_PHY (-2)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi *
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * Polarity is determined based on the PHY specific status register.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi **/
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchis32 e1000_check_polarity_82577(struct e1000_hw *hw)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi{
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi struct e1000_phy_info *phy = &hw->phy;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi s32 ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi u16 data;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGFUNC("e1000_check_polarity_82577");
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = phy->ops.read_reg(hw, I82577_PHY_STATUS_2, &data);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (!ret_val)
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi phy->cable_polarity = ((data & I82577_PHY_STATUS2_REV_POLARITY)
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi ? e1000_rev_polarity_reversed
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi : e1000_rev_polarity_normal);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi}
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi/**
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * e1000_phy_force_speed_duplex_82577 - Force speed/duplex for I82577 PHY
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @hw: pointer to the HW structure
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi *
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * Calls the PHY setup function to force speed and duplex.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi **/
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchis32 e1000_phy_force_speed_duplex_82577(struct e1000_hw *hw)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi{
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi struct e1000_phy_info *phy = &hw->phy;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi s32 ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi u16 phy_data;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi bool link;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGFUNC("e1000_phy_force_speed_duplex_82577");
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = phy->ops.read_reg(hw, PHY_CONTROL, &phy_data);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (ret_val)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi e1000_phy_force_speed_duplex_setup(hw, &phy_data);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = phy->ops.write_reg(hw, PHY_CONTROL, phy_data);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (ret_val)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi usec_delay(1);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (phy->autoneg_wait_to_complete) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGOUT("Waiting for forced speed/duplex link on 82577 phy\n");
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = e1000_phy_has_link_generic(hw, PHY_FORCE_LIMIT,
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi 100000, &link);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (ret_val)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (!link)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGOUT("Link taking longer than expected.\n");
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* Try once more */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = e1000_phy_has_link_generic(hw, PHY_FORCE_LIMIT,
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi 100000, &link);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi}
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi/**
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * e1000_get_phy_info_82577 - Retrieve I82577 PHY information
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @hw: pointer to the HW structure
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi *
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * Read PHY status to determine if link is up. If link is up, then
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * set/determine 10base-T extended distance and polarity correction. Read
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * PHY port status to determine MDI/MDIx and speed. Based on the speed,
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * determine on the cable length, local and remote receiver.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi **/
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchis32 e1000_get_phy_info_82577(struct e1000_hw *hw)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi{
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi struct e1000_phy_info *phy = &hw->phy;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi s32 ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi u16 data;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi bool link;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGFUNC("e1000_get_phy_info_82577");
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = e1000_phy_has_link_generic(hw, 1, 0, &link);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (ret_val)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (!link) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGOUT("Phy info is only valid if link is up\n");
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return -E1000_ERR_CONFIG;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi phy->polarity_correction = TRUE;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = e1000_check_polarity_82577(hw);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (ret_val)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = phy->ops.read_reg(hw, I82577_PHY_STATUS_2, &data);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (ret_val)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi phy->is_mdix = !!(data & I82577_PHY_STATUS2_MDIX);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if ((data & I82577_PHY_STATUS2_SPEED_MASK) ==
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi I82577_PHY_STATUS2_SPEED_1000MBPS) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = hw->phy.ops.get_cable_length(hw);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (ret_val)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = phy->ops.read_reg(hw, PHY_1000T_STATUS, &data);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (ret_val)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi phy->local_rx = (data & SR_1000T_LOCAL_RX_STATUS)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ? e1000_1000t_rx_status_ok
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi : e1000_1000t_rx_status_not_ok;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi phy->remote_rx = (data & SR_1000T_REMOTE_RX_STATUS)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ? e1000_1000t_rx_status_ok
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi : e1000_1000t_rx_status_not_ok;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi } else {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi phy->cable_length = E1000_CABLE_LENGTH_UNDEFINED;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi phy->local_rx = e1000_1000t_rx_status_undefined;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi phy->remote_rx = e1000_1000t_rx_status_undefined;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return E1000_SUCCESS;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi}
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi/**
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * e1000_get_cable_length_82577 - Determine cable length for 82577 PHY
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @hw: pointer to the HW structure
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi *
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * Reads the diagnostic status register and verifies result is valid before
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * placing it in the phy_cable_length field.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi **/
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchis32 e1000_get_cable_length_82577(struct e1000_hw *hw)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi{
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi struct e1000_phy_info *phy = &hw->phy;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi s32 ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi u16 phy_data, length;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGFUNC("e1000_get_cable_length_82577");
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = phy->ops.read_reg(hw, I82577_PHY_DIAG_STATUS, &phy_data);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (ret_val)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi length = ((phy_data & I82577_DSTATUS_CABLE_LENGTH) >>
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi I82577_DSTATUS_CABLE_LENGTH_SHIFT);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (length == E1000_CABLE_LENGTH_UNDEFINED)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return -E1000_ERR_PHY;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi phy->cable_length = length;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return E1000_SUCCESS;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi}
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi/**
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * e1000_write_phy_reg_gs40g - Write GS40G PHY register
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @hw: pointer to the HW structure
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @offset: register offset to write to
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @data: data to write at register offset
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi *
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * Acquires semaphore, if necessary, then writes the data to PHY register
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * at the offset. Release any acquired semaphores before exiting.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi **/
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchis32 e1000_write_phy_reg_gs40g(struct e1000_hw *hw, u32 offset, u16 data)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi{
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi s32 ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi u16 page = offset >> GS40G_PAGE_SHIFT;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGFUNC("e1000_write_phy_reg_gs40g");
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi offset = offset & GS40G_OFFSET_MASK;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = hw->phy.ops.acquire(hw);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (ret_val)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = e1000_write_phy_reg_mdic(hw, GS40G_PAGE_SELECT, page);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (ret_val)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi goto release;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = e1000_write_phy_reg_mdic(hw, offset, data);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchirelease:
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi hw->phy.ops.release(hw);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi}
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi/**
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * e1000_read_phy_reg_gs40g - Read GS40G PHY register
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @hw: pointer to the HW structure
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @offset: lower half is register offset to read to
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * upper half is page to use.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @data: data to read at register offset
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi *
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * Acquires semaphore, if necessary, then reads the data in the PHY register
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * at the offset. Release any acquired semaphores before exiting.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi **/
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchis32 e1000_read_phy_reg_gs40g(struct e1000_hw *hw, u32 offset, u16 *data)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi{
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi s32 ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi u16 page = offset >> GS40G_PAGE_SHIFT;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGFUNC("e1000_read_phy_reg_gs40g");
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi offset = offset & GS40G_OFFSET_MASK;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = hw->phy.ops.acquire(hw);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (ret_val)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = e1000_write_phy_reg_mdic(hw, GS40G_PAGE_SELECT, page);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (ret_val)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi goto release;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = e1000_read_phy_reg_mdic(hw, offset, data);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchirelease:
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi hw->phy.ops.release(hw);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi}
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi/**
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi * e1000_read_phy_reg_mphy - Read mPHY control register
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi * @hw: pointer to the HW structure
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi * @address: address to be read
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi * @data: pointer to the read data
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi *
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi * Reads the mPHY control register in the PHY at offset and stores the
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi * information read to data.
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi **/
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchis32 e1000_read_phy_reg_mphy(struct e1000_hw *hw, u32 address, u32 *data)
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi{
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi u32 mphy_ctrl = 0;
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi bool locked = FALSE;
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi bool ready;
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi DEBUGFUNC("e1000_read_phy_reg_mphy");
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi /* Check if mPHY is ready to read/write operations */
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi ready = e1000_is_mphy_ready(hw);
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi if (!ready)
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi return -E1000_ERR_PHY;
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi /* Check if mPHY access is disabled and enable it if so */
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi mphy_ctrl = E1000_READ_REG(hw, E1000_MPHY_ADDR_CTRL);
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi if (mphy_ctrl & E1000_MPHY_DIS_ACCESS) {
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi locked = TRUE;
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi ready = e1000_is_mphy_ready(hw);
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi if (!ready)
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi return -E1000_ERR_PHY;
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi mphy_ctrl |= E1000_MPHY_ENA_ACCESS;
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi E1000_WRITE_REG(hw, E1000_MPHY_ADDR_CTRL, mphy_ctrl);
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi }
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi /* Set the address that we want to read */
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi ready = e1000_is_mphy_ready(hw);
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi if (!ready)
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi return -E1000_ERR_PHY;
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi /* We mask address, because we want to use only current lane */
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi mphy_ctrl = (mphy_ctrl & ~E1000_MPHY_ADDRESS_MASK &
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi ~E1000_MPHY_ADDRESS_FNC_OVERRIDE) |
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi (address & E1000_MPHY_ADDRESS_MASK);
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi E1000_WRITE_REG(hw, E1000_MPHY_ADDR_CTRL, mphy_ctrl);
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi /* Read data from the address */
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi ready = e1000_is_mphy_ready(hw);
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi if (!ready)
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi return -E1000_ERR_PHY;
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi *data = E1000_READ_REG(hw, E1000_MPHY_DATA);
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi /* Disable access to mPHY if it was originally disabled */
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi if (locked)
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi ready = e1000_is_mphy_ready(hw);
ea4c6b78cebe2a3687fa43deeedf6212a124d817Robert Mustacchi if (!ready)
ea4c6b78cebe2a3687fa43deeedf6212a124d817Robert Mustacchi return -E1000_ERR_PHY;
ea4c6b78cebe2a3687fa43deeedf6212a124d817Robert Mustacchi E1000_WRITE_REG(hw, E1000_MPHY_ADDR_CTRL,
ea4c6b78cebe2a3687fa43deeedf6212a124d817Robert Mustacchi E1000_MPHY_DIS_ACCESS);
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi return E1000_SUCCESS;
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi}
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi/**
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi * e1000_write_phy_reg_mphy - Write mPHY control register
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi * @hw: pointer to the HW structure
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi * @address: address to write to
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi * @data: data to write to register at offset
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi * @line_override: used when we want to use different line than default one
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi *
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi * Writes data to mPHY control register.
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi **/
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchis32 e1000_write_phy_reg_mphy(struct e1000_hw *hw, u32 address, u32 data,
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi bool line_override)
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi{
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi u32 mphy_ctrl = 0;
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi bool locked = FALSE;
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi bool ready;
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi DEBUGFUNC("e1000_write_phy_reg_mphy");
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi /* Check if mPHY is ready to read/write operations */
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi ready = e1000_is_mphy_ready(hw);
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi if (!ready)
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi return -E1000_ERR_PHY;
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi /* Check if mPHY access is disabled and enable it if so */
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi mphy_ctrl = E1000_READ_REG(hw, E1000_MPHY_ADDR_CTRL);
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi if (mphy_ctrl & E1000_MPHY_DIS_ACCESS) {
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi locked = TRUE;
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi ready = e1000_is_mphy_ready(hw);
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi if (!ready)
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi return -E1000_ERR_PHY;
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi mphy_ctrl |= E1000_MPHY_ENA_ACCESS;
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi E1000_WRITE_REG(hw, E1000_MPHY_ADDR_CTRL, mphy_ctrl);
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi }
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi /* Set the address that we want to read */
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi ready = e1000_is_mphy_ready(hw);
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi if (!ready)
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi return -E1000_ERR_PHY;
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi /* We mask address, because we want to use only current lane */
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi if (line_override)
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi mphy_ctrl |= E1000_MPHY_ADDRESS_FNC_OVERRIDE;
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi else
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi mphy_ctrl &= ~E1000_MPHY_ADDRESS_FNC_OVERRIDE;
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi mphy_ctrl = (mphy_ctrl & ~E1000_MPHY_ADDRESS_MASK) |
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi (address & E1000_MPHY_ADDRESS_MASK);
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi E1000_WRITE_REG(hw, E1000_MPHY_ADDR_CTRL, mphy_ctrl);
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi /* Read data from the address */
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi ready = e1000_is_mphy_ready(hw);
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi if (!ready)
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi return -E1000_ERR_PHY;
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi E1000_WRITE_REG(hw, E1000_MPHY_DATA, data);
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi /* Disable access to mPHY if it was originally disabled */
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi if (locked)
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi ready = e1000_is_mphy_ready(hw);
ea4c6b78cebe2a3687fa43deeedf6212a124d817Robert Mustacchi if (!ready)
ea4c6b78cebe2a3687fa43deeedf6212a124d817Robert Mustacchi return -E1000_ERR_PHY;
ea4c6b78cebe2a3687fa43deeedf6212a124d817Robert Mustacchi E1000_WRITE_REG(hw, E1000_MPHY_ADDR_CTRL,
ea4c6b78cebe2a3687fa43deeedf6212a124d817Robert Mustacchi E1000_MPHY_DIS_ACCESS);
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi return E1000_SUCCESS;
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi}
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi/**
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi * e1000_is_mphy_ready - Check if mPHY control register is not busy
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi * @hw: pointer to the HW structure
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi *
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi * Returns mPHY control register status.
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi **/
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchibool e1000_is_mphy_ready(struct e1000_hw *hw)
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi{
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi u16 retry_count = 0;
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi u32 mphy_ctrl = 0;
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi bool ready = FALSE;
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi while (retry_count < 2) {
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi mphy_ctrl = E1000_READ_REG(hw, E1000_MPHY_ADDR_CTRL);
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi if (mphy_ctrl & E1000_MPHY_BUSY) {
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi usec_delay(20);
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi retry_count++;
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi continue;
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi }
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi ready = TRUE;
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi break;
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi }
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi if (!ready)
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi DEBUGOUT("ERROR READING mPHY control register, phy is busy.\n");
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi return ready;
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi}