1294838Szbb/*- 2294838Szbb******************************************************************************* 3294838SzbbCopyright (C) 2015 Annapurna Labs Ltd. 4294838Szbb 5294838SzbbThis file may be licensed under the terms of the Annapurna Labs Commercial 6294838SzbbLicense Agreement. 7294838Szbb 8294838SzbbAlternatively, this file can be distributed under the terms of the GNU General 9294838SzbbPublic License V2 as published by the Free Software Foundation and can be 10294838Szbbfound at http://www.gnu.org/licenses/gpl-2.0.html 11294838Szbb 12294838SzbbAlternatively, redistribution and use in source and binary forms, with or 13294838Szbbwithout modification, are permitted provided that the following conditions are 14294838Szbbmet: 15294838Szbb 16294838Szbb * Redistributions of source code must retain the above copyright notice, 17294838Szbbthis list of conditions and the following disclaimer. 18294838Szbb 19294838Szbb * Redistributions in binary form must reproduce the above copyright 20294838Szbbnotice, this list of conditions and the following disclaimer in 21294838Szbbthe documentation and/or other materials provided with the 22294838Szbbdistribution. 23294838Szbb 24294838SzbbTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 25294838SzbbANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 26294838SzbbWARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 27294838SzbbDISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 28294838SzbbANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 29294838Szbb(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 30294838SzbbLOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 31294838SzbbANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 32294838Szbb(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 33294838SzbbSOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 34294838Szbb 35294838Szbb*******************************************************************************/ 36294838Szbb/** 37294838Szbb * Ethernet 38294838Szbb * @{ 39294838Szbb * @file al_hal_eth_kr.c 40294838Szbb * 41294838Szbb * @brief KR HAL driver for main functions (auto-neg, Link Training) 42294838Szbb * 43294838Szbb */ 44294838Szbb 45294838Szbb#include "al_hal_eth_kr.h" 46294838Szbb#include "al_hal_eth_mac_regs.h" 47294838Szbb#include "al_hal_an_lt_wrapper_regs.h" 48294838Szbb 49294838Szbbenum al_eth_lt_unit_rev { 50294838Szbb AL_ETH_LT_UNIT_REV_1 = 0, 51294838Szbb AL_ETH_LT_UNIT_REV_2, 52294838Szbb 53294838Szbb AL_ETH_LT_UNIT_REV_MAX 54294838Szbb}; 55294838Szbb 56294838Szbbenum al_eth_an_lt_regs_ids { 57294838Szbb AL_ETH_KR_AN_CONTROL = 0, 58294838Szbb AL_ETH_KR_AN_STATUS, 59294838Szbb AL_ETH_KR_AN_ADV0, 60294838Szbb AL_ETH_KR_AN_ADV1, 61294838Szbb AL_ETH_KR_AN_ADV2, 62294838Szbb AL_ETH_KR_AN_REM_ADV0, 63294838Szbb AL_ETH_KR_AN_REM_ADV1, 64294838Szbb AL_ETH_KR_AN_REM_ADV2, 65294838Szbb AL_ETH_KR_PMD_CONTROL, 66294838Szbb AL_ETH_KR_PMD_STATUS, 67294838Szbb AL_ETH_KR_PMD_LP_COEF_UP, 68294838Szbb AL_ETH_KR_PMD_LP_STATUS_REPORT, 69294838Szbb AL_ETH_KR_PMD_LD_COEF_UP, 70294838Szbb AL_ETH_KR_PMD_LD_STATUS_REPORT, 71294838Szbb AL_ETH_KR_AN_XNP_ADV0, 72294838Szbb AL_ETH_KR_AN_XNP_ADV1, 73294838Szbb AL_ETH_KR_AN_XNP_ADV2, 74294838Szbb AL_ETH_KR_AN_REM_XNP_ADV0, 75294838Szbb AL_ETH_KR_AN_REM_XNP_ADV1, 76294838Szbb AL_ETH_KR_AN_REM_XNP_ADV2, 77294838Szbb}; 78294838Szbb 79294838Szbbstatic uint32_t al_eth_an_lt_regs_addr[][AL_ETH_LT_UNIT_REV_MAX] = { 80294838Szbb [AL_ETH_KR_AN_CONTROL] = {0 , 0x0}, 81294838Szbb [AL_ETH_KR_AN_STATUS] = {1 , 0x4}, 82294838Szbb [AL_ETH_KR_AN_ADV0] = {16 , 0x8}, 83294838Szbb [AL_ETH_KR_AN_ADV1] = {17 , 0xc}, 84294838Szbb [AL_ETH_KR_AN_ADV2] = {18 , 0x10}, 85294838Szbb [AL_ETH_KR_AN_REM_ADV0] = {19 , 0x14}, 86294838Szbb [AL_ETH_KR_AN_REM_ADV1] = {20 , 0x18}, 87294838Szbb [AL_ETH_KR_AN_REM_ADV2] = {21 , 0x1c}, 88294838Szbb [AL_ETH_KR_PMD_CONTROL] = {150, 0x400}, 89294838Szbb [AL_ETH_KR_PMD_STATUS] = {151, 0x404}, 90294838Szbb [AL_ETH_KR_PMD_LP_COEF_UP] = {152, 0x408}, 91294838Szbb [AL_ETH_KR_PMD_LP_STATUS_REPORT] = {153, 0x40c}, 92294838Szbb [AL_ETH_KR_PMD_LD_COEF_UP] = {154, 0x410}, 93294838Szbb [AL_ETH_KR_PMD_LD_STATUS_REPORT] = {155, 0x414}, 94294838Szbb [AL_ETH_KR_AN_XNP_ADV0] = {22 , 0x24}, 95294838Szbb [AL_ETH_KR_AN_XNP_ADV1] = {23 , 0x28}, 96294838Szbb [AL_ETH_KR_AN_XNP_ADV2] = {24 , 0x2c}, 97294838Szbb [AL_ETH_KR_AN_REM_XNP_ADV0] = {25 , 0x30}, 98294838Szbb [AL_ETH_KR_AN_REM_XNP_ADV1] = {26 , 0x34}, 99294838Szbb [AL_ETH_KR_AN_REM_XNP_ADV2] = {27 , 0x38}, 100294838Szbb}; 101294838Szbb 102294838Szbb 103294838Szbb/* 104294838Szbb * AN(Auto Negotiation) registers 105294838Szbb * (read / write indirect with al_eth_an_reg_read/write) 106294838Szbb */ 107294838Szbb#define AL_ETH_KR_AN_CONTROL_RESTART AL_BIT(9) 108294838Szbb#define AL_ETH_KR_AN_CONTROL_ENABLE AL_BIT(12) 109294838Szbb#define AL_ETH_KR_AN_CONTROL_NP_ENABLE AL_BIT(13) 110294838Szbb 111294838Szbb#define AL_ETH_KR_AN_STATUS_COMPLETED AL_BIT(5) 112294838Szbb#define AL_ETH_KR_AN_STATUS_BASE_PAGE_RECEIVED AL_BIT(6) 113294838Szbb#define AL_ETH_KR_AN_STATUS_CHECK_MASK 0xFF0A 114294838Szbb#define AL_ETH_KR_AN_STATUS_CHECK_NO_ERROR 0x0008 115294838Szbb 116294838Szbb/* AN advertising registers parsing */ 117294838Szbb/* register 1 */ 118294838Szbb#define AL_ETH_KR_AN_ADV1_SEL_FIELD_MASK 0x001f 119294838Szbb#define AL_ETH_KR_AN_ADV1_SEL_FIELD_SHIFT 0 120294838Szbb#define AL_ETH_KR_AN_ADV1_ECHOED_NONCE_MASK 0x03e0 121294838Szbb#define AL_ETH_KR_AN_ADV1_ECHOED_NONCE_SHIFT 5 122294838Szbb#define AL_ETH_KR_AN_ADV1_CAPABILITY_MASK 0x1c00 123294838Szbb#define AL_ETH_KR_AN_ADV1_CAPABILITY_SHIFT 10 124294838Szbb#define AL_ETH_KR_AN_ADV1_REM_FAULT_MASK 0x2000 125294838Szbb#define AL_ETH_KR_AN_ADV1_REM_FAULT_SHIFT 13 126294838Szbb#define AL_ETH_KR_AN_ADV1_ACK_MASK 0x4000 127294838Szbb#define AL_ETH_KR_AN_ADV1_ACK_SHIFT 14 128294838Szbb#define AL_ETH_KR_AN_ADV1_NEXT_PAGE_MASK 0x8000 129294838Szbb#define AL_ETH_KR_AN_ADV1_NEXT_PAGE_SHIFT 15 130294838Szbb/* register 2 */ 131294838Szbb#define AL_ETH_KR_AN_ADV2_TX_NONCE_MASK 0x001f 132294838Szbb#define AL_ETH_KR_AN_ADV2_TX_NONCE_SHIFT 0 133294838Szbb#define AL_ETH_KR_AN_ADV2_TECH_MASK 0xffe0 134294838Szbb#define AL_ETH_KR_AN_ADV2_TECH_SHIFT 5 135294838Szbb/* register 3 */ 136294838Szbb/* TECH field in the third register is extended to the field in the second 137294838Szbb * register and it is currently reserved (should be always 0) */ 138294838Szbb#define AL_ETH_KR_AN_ADV3_TECH_MASK 0x1fff 139294838Szbb#define AL_ETH_KR_AN_ADV3_TECH_SHIFT 0 140294838Szbb#define AL_ETH_KR_AN_ADV3_FEC_MASK 0xc000 141294838Szbb#define AL_ETH_KR_AN_ADV3_FEC_SHIFT 14 142294838Szbb 143294838Szbb/* Next Page Fields */ 144294838Szbb/* register 1 */ 145294838Szbb#define AL_ETH_KR_AN_NP_ADV1_DATA1_MASK 0x07ff 146294838Szbb#define AL_ETH_KR_AN_NP_ADV1_DATA1_SHIFT 0 147294838Szbb#define AL_ETH_KR_AN_NP_ADV1_TOGGLE_MASK 0x0800 148294838Szbb#define AL_ETH_KR_AN_NP_ADV1_TOGGLE_SHIFT 11 149294838Szbb#define AL_ETH_KR_AN_NP_ADV1_ACK2_MASK 0x1000 150294838Szbb#define AL_ETH_KR_AN_NP_ADV1_ACK2_SHIFT 12 151294838Szbb#define AL_ETH_KR_AN_NP_ADV1_MSG_PAGE_MASK 0x2000 152294838Szbb#define AL_ETH_KR_AN_NP_ADV1_MSG_PAGE_SHIFT 13 153294838Szbb#define AL_ETH_KR_AN_NP_ADV1_NP_MASK 0x8000 154294838Szbb#define AL_ETH_KR_AN_NP_ADV1_NP_SHIFT 15 155294838Szbb 156294838Szbb/* 157294838Szbb * LT(Link Training) registers 158294838Szbb * (read / write indirect with al_eth_pma_reg_read/write) 159294838Szbb */ 160294838Szbb#define AL_ETH_KR_PMD_CONTROL_RESTART 0 161294838Szbb#define AL_ETH_KR_PMD_CONTROL_ENABLE 1 162294838Szbb 163294838Szbb#define AL_ETH_KR_PMD_STATUS_RECEIVER_COMPLETED_SHIFT 0 164294838Szbb#define AL_ETH_KR_PMD_STATUS_RECEIVER_FRAME_LOCK_SHIFT 1 165294838Szbb#define AL_ETH_KR_PMD_STATUS_RECEIVER_START_UP_PROTO_PROG_SHIFT 2 166294838Szbb#define AL_ETH_KR_PMD_STATUS_FAILURE_SHIFT 3 167294838Szbb 168294838Szbb#define AL_ETH_KR_PMD_LP_COEF_UP_MINUS_MASK 0x0003 169294838Szbb#define AL_ETH_KR_PMD_LP_COEF_UP_MINUS_SHIFT 0 170294838Szbb#define AL_ETH_KR_PMD_LP_COEF_UP_ZERO_MASK 0x000C 171294838Szbb#define AL_ETH_KR_PMD_LP_COEF_UP_ZERO_SHIFT 2 172294838Szbb#define AL_ETH_KR_PMD_LP_COEF_UP_PLUS_MASK 0x0030 173294838Szbb#define AL_ETH_KR_PMD_LP_COEF_UP_PLUS_SHIFT 4 174294838Szbb#define AL_ETH_KR_PMD_LP_COEF_UP_INITIALIZE_SHIFT 12 175294838Szbb#define AL_ETH_KR_PMD_LP_COEF_UP_PRESET_SHIFT 13 176294838Szbb 177294838Szbb#define AL_ETH_KR_PMD_LP_STATUS_REPORT_MINUS_MASK 0x0003 178294838Szbb#define AL_ETH_KR_PMD_LP_STATUS_REPORT_MINUS_SHIFT 0 179294838Szbb#define AL_ETH_KR_PMD_LP_STATUS_REPORT_ZERO_MASK 0x000C 180294838Szbb#define AL_ETH_KR_PMD_LP_STATUS_REPORT_ZERO_SHIFT 2 181294838Szbb#define AL_ETH_KR_PMD_LP_STATUS_REPORT_PLUS_MASK 0x0030 182294838Szbb#define AL_ETH_KR_PMD_LP_STATUS_REPORT_PLUS_SHIFT 4 183294838Szbb#define AL_ETH_KR_PMD_LP_STATUS_RECEIVER_READY_SHIFT 15 184294838Szbb 185294838Szbb#define AL_ETH_KR_PMD_LD_COEF_UP_MINUS_MASK 0x0003 186294838Szbb#define AL_ETH_KR_PMD_LD_COEF_UP_MINUS_SHIFT 0 187294838Szbb#define AL_ETH_KR_PMD_LD_COEF_UP_ZERO_MASK 0x000C 188294838Szbb#define AL_ETH_KR_PMD_LD_COEF_UP_ZERO_SHIFT 2 189294838Szbb#define AL_ETH_KR_PMD_LD_COEF_UP_PLUS_MASK 0x0030 190294838Szbb#define AL_ETH_KR_PMD_LD_COEF_UP_PLUS_SHIFT 4 191294838Szbb#define AL_ETH_KR_PMD_LD_COEF_UP_INITIALIZE_SHIFT 12 192294838Szbb#define AL_ETH_KR_PMD_LD_COEF_UP_PRESET_SHIFT 13 193294838Szbb 194294838Szbb#define AL_ETH_KR_PMD_LD_STATUS_REPORT_MINUS_MASK 0x0003 195294838Szbb#define AL_ETH_KR_PMD_LD_STATUS_REPORT_MINUS_SHIFT 0 196294838Szbb#define AL_ETH_KR_PMD_LD_STATUS_REPORT_ZERO_MASK 0x000C 197294838Szbb#define AL_ETH_KR_PMD_LD_STATUS_REPORT_ZERO_SHIFT 2 198294838Szbb#define AL_ETH_KR_PMD_LD_STATUS_REPORT_PLUS_MASK 0x0030 199294838Szbb#define AL_ETH_KR_PMD_LD_STATUS_REPORT_PLUS_SHIFT 4 200294838Szbb#define AL_ETH_KR_PMD_LD_STATUS_REPORT_RECEIVER_READY_SHIFT 15 201294838Szbb 202294838Szbb 203294838Szbbenum al_eth_an_lt_regs { 204294838Szbb AL_ETH_AN_REGS, 205294838Szbb AL_ETH_LT_REGS, 206294838Szbb}; 207294838Szbb 208294838Szbbstatic uint16_t al_eth_an_lt_reg_read( 209294838Szbb struct al_hal_eth_adapter *adapter, 210294838Szbb enum al_eth_an_lt_regs_ids reg_id, 211294838Szbb enum al_eth_an_lt_regs an_lt, 212294838Szbb enum al_eth_an_lt_lane lane) 213294838Szbb{ 214294838Szbb uint32_t val; 215294838Szbb uint16_t reg_addr; 216294838Szbb 217294838Szbb if (adapter->rev_id < AL_ETH_REV_ID_3) { 218294838Szbb al_assert(lane == AL_ETH_AN__LT_LANE_0); 219294838Szbb 220294838Szbb reg_addr = al_eth_an_lt_regs_addr[reg_id][AL_ETH_LT_UNIT_REV_1]; 221294838Szbb if (an_lt == AL_ETH_AN_REGS) { 222294838Szbb al_reg_write32(&adapter->mac_regs_base->kr.an_addr, reg_addr); 223294838Szbb val = al_reg_read32(&adapter->mac_regs_base->kr.an_data); 224294838Szbb } else { 225294838Szbb al_reg_write32(&adapter->mac_regs_base->kr.pma_addr, reg_addr); 226294838Szbb val = al_reg_read32(&adapter->mac_regs_base->kr.pma_data); 227294838Szbb } 228294838Szbb } else { 229294838Szbb struct al_an_lt_wrapper_regs *regs = NULL; 230294838Szbb 231294838Szbb reg_addr = al_eth_an_lt_regs_addr[reg_id][AL_ETH_LT_UNIT_REV_2]; 232294838Szbb 233294838Szbb switch (lane) { 234294838Szbb case AL_ETH_AN__LT_LANE_0: 235294838Szbb al_reg_write32(&adapter->mac_regs_base->gen_v3.an_lt_0_addr, 236294838Szbb (uintptr_t)®s->an_lt[adapter->curr_lt_unit].addr); 237294838Szbb al_reg_write32(&adapter->mac_regs_base->gen_v3.an_lt_0_data, 238294838Szbb reg_addr); 239294838Szbb 240294838Szbb al_reg_write32(&adapter->mac_regs_base->gen_v3.an_lt_0_addr, 241294838Szbb (uintptr_t)®s->an_lt[adapter->curr_lt_unit].data); 242294838Szbb val = al_reg_read32(&adapter->mac_regs_base->gen_v3.an_lt_0_data); 243294838Szbb break; 244294838Szbb case AL_ETH_AN__LT_LANE_1: 245294838Szbb al_reg_write32(&adapter->mac_regs_base->gen_v3.an_lt_1_addr, 246294838Szbb (uintptr_t)®s->an_lt[adapter->curr_lt_unit].addr); 247294838Szbb al_reg_write32(&adapter->mac_regs_base->gen_v3.an_lt_1_data, 248294838Szbb reg_addr); 249294838Szbb 250294838Szbb al_reg_write32(&adapter->mac_regs_base->gen_v3.an_lt_1_addr, 251294838Szbb (uintptr_t)®s->an_lt[adapter->curr_lt_unit].data); 252294838Szbb val = al_reg_read32(&adapter->mac_regs_base->gen_v3.an_lt_1_data); 253294838Szbb break; 254294838Szbb case AL_ETH_AN__LT_LANE_2: 255294838Szbb al_reg_write32(&adapter->mac_regs_base->gen_v3.an_lt_2_addr, 256294838Szbb (uintptr_t)®s->an_lt[adapter->curr_lt_unit].addr); 257294838Szbb al_reg_write32(&adapter->mac_regs_base->gen_v3.an_lt_2_data, 258294838Szbb reg_addr); 259294838Szbb 260294838Szbb al_reg_write32(&adapter->mac_regs_base->gen_v3.an_lt_2_addr, 261294838Szbb (uintptr_t)®s->an_lt[adapter->curr_lt_unit].data); 262294838Szbb val = al_reg_read32(&adapter->mac_regs_base->gen_v3.an_lt_2_data); 263294838Szbb break; 264294838Szbb case AL_ETH_AN__LT_LANE_3: 265294838Szbb al_reg_write32(&adapter->mac_regs_base->gen_v3.an_lt_3_addr, 266294838Szbb (uintptr_t)®s->an_lt[adapter->curr_lt_unit].addr); 267294838Szbb al_reg_write32(&adapter->mac_regs_base->gen_v3.an_lt_3_data, 268294838Szbb reg_addr); 269294838Szbb 270294838Szbb al_reg_write32(&adapter->mac_regs_base->gen_v3.an_lt_3_addr, 271294838Szbb (uintptr_t)®s->an_lt[adapter->curr_lt_unit].data); 272294838Szbb val = al_reg_read32(&adapter->mac_regs_base->gen_v3.an_lt_3_data); 273294838Szbb break; 274294838Szbb default: 275294838Szbb al_err("%s: Unknown Lane %d\n", __func__, lane); 276294838Szbb return 0; 277294838Szbb } 278294838Szbb } 279294838Szbb 280294838Szbb 281294838Szbb al_dbg("[%s]: %s - (%s) lane %d, reg %d, val 0x%x", adapter->name, __func__, 282294838Szbb (an_lt == AL_ETH_AN_REGS) ? "AN" : "LT", lane, reg_addr, val); 283294838Szbb 284294838Szbb return (uint16_t)val; 285294838Szbb} 286294838Szbb 287294838Szbbstatic void al_eth_an_lt_reg_write( 288294838Szbb struct al_hal_eth_adapter *adapter, 289294838Szbb enum al_eth_an_lt_regs_ids reg_id, 290294838Szbb enum al_eth_an_lt_regs an_lt, 291294838Szbb enum al_eth_an_lt_lane lane, 292294838Szbb uint16_t val) 293294838Szbb{ 294294838Szbb uint16_t reg_addr; 295294838Szbb 296294838Szbb if (adapter->rev_id < AL_ETH_REV_ID_3) { 297294838Szbb reg_addr = al_eth_an_lt_regs_addr[reg_id][AL_ETH_LT_UNIT_REV_1]; 298294838Szbb if (an_lt == AL_ETH_AN_REGS) { 299294838Szbb al_reg_write32(&adapter->mac_regs_base->kr.an_addr, reg_addr); 300294838Szbb al_reg_write32(&adapter->mac_regs_base->kr.an_data, val); 301294838Szbb } else { 302294838Szbb al_reg_write32(&adapter->mac_regs_base->kr.pma_addr, reg_addr); 303294838Szbb al_reg_write32(&adapter->mac_regs_base->kr.pma_data, val); 304294838Szbb } 305294838Szbb } else { 306294838Szbb struct al_an_lt_wrapper_regs *regs = NULL; 307294838Szbb 308294838Szbb reg_addr = al_eth_an_lt_regs_addr[reg_id][AL_ETH_LT_UNIT_REV_2]; 309294838Szbb 310294838Szbb switch (lane) { 311294838Szbb case AL_ETH_AN__LT_LANE_0: 312294838Szbb al_reg_write32(&adapter->mac_regs_base->gen_v3.an_lt_0_addr, 313294838Szbb (uintptr_t)®s->an_lt[adapter->curr_lt_unit].addr); 314294838Szbb al_reg_write32(&adapter->mac_regs_base->gen_v3.an_lt_0_data, 315294838Szbb reg_addr); 316294838Szbb 317294838Szbb al_reg_write32(&adapter->mac_regs_base->gen_v3.an_lt_0_addr, 318294838Szbb (uintptr_t)®s->an_lt[adapter->curr_lt_unit].data); 319294838Szbb al_reg_write32(&adapter->mac_regs_base->gen_v3.an_lt_0_data, 320294838Szbb val); 321294838Szbb break; 322294838Szbb case AL_ETH_AN__LT_LANE_1: 323294838Szbb al_reg_write32(&adapter->mac_regs_base->gen_v3.an_lt_1_addr, 324294838Szbb (uintptr_t)®s->an_lt[adapter->curr_lt_unit].addr); 325294838Szbb al_reg_write32(&adapter->mac_regs_base->gen_v3.an_lt_1_data, 326294838Szbb reg_addr); 327294838Szbb 328294838Szbb al_reg_write32(&adapter->mac_regs_base->gen_v3.an_lt_1_addr, 329294838Szbb (uintptr_t)®s->an_lt[adapter->curr_lt_unit].data); 330294838Szbb al_reg_write32(&adapter->mac_regs_base->gen_v3.an_lt_1_data, 331294838Szbb val); 332294838Szbb break; 333294838Szbb case AL_ETH_AN__LT_LANE_2: 334294838Szbb al_reg_write32(&adapter->mac_regs_base->gen_v3.an_lt_2_addr, 335294838Szbb (uintptr_t)®s->an_lt[adapter->curr_lt_unit].addr); 336294838Szbb al_reg_write32(&adapter->mac_regs_base->gen_v3.an_lt_2_data, 337294838Szbb reg_addr); 338294838Szbb 339294838Szbb al_reg_write32(&adapter->mac_regs_base->gen_v3.an_lt_2_addr, 340294838Szbb (uintptr_t)®s->an_lt[adapter->curr_lt_unit].data); 341294838Szbb al_reg_write32(&adapter->mac_regs_base->gen_v3.an_lt_2_data, 342294838Szbb val); 343294838Szbb break; 344294838Szbb case AL_ETH_AN__LT_LANE_3: 345294838Szbb al_reg_write32(&adapter->mac_regs_base->gen_v3.an_lt_3_addr, 346294838Szbb (uintptr_t)®s->an_lt[adapter->curr_lt_unit].addr); 347294838Szbb al_reg_write32(&adapter->mac_regs_base->gen_v3.an_lt_3_data, 348294838Szbb reg_addr); 349294838Szbb 350294838Szbb al_reg_write32(&adapter->mac_regs_base->gen_v3.an_lt_3_addr, 351294838Szbb (uintptr_t)®s->an_lt[adapter->curr_lt_unit].data); 352294838Szbb al_reg_write32(&adapter->mac_regs_base->gen_v3.an_lt_3_data, 353294838Szbb val); 354294838Szbb break; 355294838Szbb default: 356294838Szbb al_err("%s: Unknown Lane %d\n", __func__, lane); 357294838Szbb return; 358294838Szbb } 359294838Szbb } 360294838Szbb 361294838Szbb 362294838Szbb al_dbg("[%s]: %s - (%s) lane %d, reg %d, val 0x%x", adapter->name, __func__, 363294838Szbb (an_lt == AL_ETH_AN_REGS) ? "AN" : "LT", lane, reg_addr, val); 364294838Szbb} 365294838Szbb 366294838Szbbstatic void al_eth_an_lt_unit_config(struct al_hal_eth_adapter *adapter) 367294838Szbb{ 368294838Szbb struct al_an_lt_wrapper_regs *regs = NULL; 369294838Szbb uint32_t cfg_lane_0 = (AN_LT_WRAPPER_GEN_CFG_BYPASS_RX | AN_LT_WRAPPER_GEN_CFG_BYPASS_TX); 370294838Szbb uint32_t cfg_lane_1 = (AN_LT_WRAPPER_GEN_CFG_BYPASS_RX | AN_LT_WRAPPER_GEN_CFG_BYPASS_TX); 371294838Szbb uint32_t cfg_lane_2 = (AN_LT_WRAPPER_GEN_CFG_BYPASS_RX | AN_LT_WRAPPER_GEN_CFG_BYPASS_TX); 372294838Szbb uint32_t cfg_lane_3 = (AN_LT_WRAPPER_GEN_CFG_BYPASS_RX | AN_LT_WRAPPER_GEN_CFG_BYPASS_TX); 373294838Szbb 374294838Szbb switch (adapter->mac_mode) { 375294838Szbb case AL_ETH_MAC_MODE_10GbE_Serial: 376294838Szbb cfg_lane_0 = 0; 377294838Szbb AL_REG_FIELD_SET(cfg_lane_0, 378294838Szbb AN_LT_WRAPPER_GEN_CFG_AN_LT_SEL_RX_MASK, 379294838Szbb AN_LT_WRAPPER_GEN_CFG_AN_LT_SEL_RX_SHIFT, 380294838Szbb AL_ETH_AN_LT_UNIT_20_BIT); 381294838Szbb AL_REG_FIELD_SET(cfg_lane_0, 382294838Szbb AN_LT_WRAPPER_GEN_CFG_AN_LT_SEL_TX_MASK, 383294838Szbb AN_LT_WRAPPER_GEN_CFG_AN_LT_SEL_TX_SHIFT, 384294838Szbb AL_ETH_AN_LT_UNIT_20_BIT); 385294838Szbb 386294838Szbb adapter->curr_lt_unit = AL_ETH_AN_LT_UNIT_20_BIT; 387294838Szbb 388294838Szbb break; 389294838Szbb case AL_ETH_MAC_MODE_KR_LL_25G: 390294838Szbb cfg_lane_0 = 0; 391294838Szbb AL_REG_FIELD_SET(cfg_lane_0, 392294838Szbb AN_LT_WRAPPER_GEN_CFG_AN_LT_SEL_RX_MASK, 393294838Szbb AN_LT_WRAPPER_GEN_CFG_AN_LT_SEL_RX_SHIFT, 394294838Szbb AL_ETH_AN_LT_UNIT_32_BIT); 395294838Szbb AL_REG_FIELD_SET(cfg_lane_0, 396294838Szbb AN_LT_WRAPPER_GEN_CFG_AN_LT_SEL_TX_MASK, 397294838Szbb AN_LT_WRAPPER_GEN_CFG_AN_LT_SEL_TX_SHIFT, 398294838Szbb AL_ETH_AN_LT_UNIT_32_BIT); 399294838Szbb 400294838Szbb adapter->curr_lt_unit = AL_ETH_AN_LT_UNIT_32_BIT; 401294838Szbb 402294838Szbb break; 403294838Szbb case AL_ETH_MAC_MODE_XLG_LL_40G: 404294838Szbb cfg_lane_0 = 0; 405294838Szbb AL_REG_FIELD_SET(cfg_lane_0, 406294838Szbb AN_LT_WRAPPER_GEN_CFG_AN_LT_SEL_RX_MASK, 407294838Szbb AN_LT_WRAPPER_GEN_CFG_AN_LT_SEL_RX_SHIFT, 408294838Szbb AL_ETH_AN_LT_UNIT_16_BIT); 409294838Szbb AL_REG_FIELD_SET(cfg_lane_0, 410294838Szbb AN_LT_WRAPPER_GEN_CFG_AN_LT_SEL_TX_MASK, 411294838Szbb AN_LT_WRAPPER_GEN_CFG_AN_LT_SEL_TX_SHIFT, 412294838Szbb AL_ETH_AN_LT_UNIT_16_BIT); 413294838Szbb 414294838Szbb cfg_lane_1 = 0; 415294838Szbb AL_REG_FIELD_SET(cfg_lane_1, 416294838Szbb AN_LT_WRAPPER_GEN_CFG_AN_LT_SEL_RX_MASK, 417294838Szbb AN_LT_WRAPPER_GEN_CFG_AN_LT_SEL_RX_SHIFT, 418294838Szbb AL_ETH_AN_LT_UNIT_16_BIT); 419294838Szbb AL_REG_FIELD_SET(cfg_lane_1, 420294838Szbb AN_LT_WRAPPER_GEN_CFG_AN_LT_SEL_TX_MASK, 421294838Szbb AN_LT_WRAPPER_GEN_CFG_AN_LT_SEL_TX_SHIFT, 422294838Szbb AL_ETH_AN_LT_UNIT_16_BIT); 423294838Szbb 424294838Szbb cfg_lane_2 = 0; 425294838Szbb AL_REG_FIELD_SET(cfg_lane_2, 426294838Szbb AN_LT_WRAPPER_GEN_CFG_AN_LT_SEL_RX_MASK, 427294838Szbb AN_LT_WRAPPER_GEN_CFG_AN_LT_SEL_RX_SHIFT, 428294838Szbb AL_ETH_AN_LT_UNIT_16_BIT); 429294838Szbb AL_REG_FIELD_SET(cfg_lane_2, 430294838Szbb AN_LT_WRAPPER_GEN_CFG_AN_LT_SEL_TX_MASK, 431294838Szbb AN_LT_WRAPPER_GEN_CFG_AN_LT_SEL_TX_SHIFT, 432294838Szbb AL_ETH_AN_LT_UNIT_16_BIT); 433294838Szbb 434294838Szbb cfg_lane_3 = 0; 435294838Szbb AL_REG_FIELD_SET(cfg_lane_3, 436294838Szbb AN_LT_WRAPPER_GEN_CFG_AN_LT_SEL_RX_MASK, 437294838Szbb AN_LT_WRAPPER_GEN_CFG_AN_LT_SEL_RX_SHIFT, 438294838Szbb AL_ETH_AN_LT_UNIT_16_BIT); 439294838Szbb AL_REG_FIELD_SET(cfg_lane_3, 440294838Szbb AN_LT_WRAPPER_GEN_CFG_AN_LT_SEL_TX_MASK, 441294838Szbb AN_LT_WRAPPER_GEN_CFG_AN_LT_SEL_TX_SHIFT, 442294838Szbb AL_ETH_AN_LT_UNIT_16_BIT); 443294838Szbb 444294838Szbb adapter->curr_lt_unit = AL_ETH_AN_LT_UNIT_16_BIT; 445294838Szbb 446294838Szbb break; 447294838Szbb case AL_ETH_MAC_MODE_XLG_LL_50G: 448294838Szbb cfg_lane_0 = 0; 449294838Szbb AL_REG_FIELD_SET(cfg_lane_0, 450294838Szbb AN_LT_WRAPPER_GEN_CFG_AN_LT_SEL_RX_MASK, 451294838Szbb AN_LT_WRAPPER_GEN_CFG_AN_LT_SEL_RX_SHIFT, 452294838Szbb AL_ETH_AN_LT_UNIT_32_BIT); 453294838Szbb AL_REG_FIELD_SET(cfg_lane_0, 454294838Szbb AN_LT_WRAPPER_GEN_CFG_AN_LT_SEL_TX_MASK, 455294838Szbb AN_LT_WRAPPER_GEN_CFG_AN_LT_SEL_TX_SHIFT, 456294838Szbb AL_ETH_AN_LT_UNIT_32_BIT); 457294838Szbb 458294838Szbb cfg_lane_1 = 0; 459294838Szbb AL_REG_FIELD_SET(cfg_lane_1, 460294838Szbb AN_LT_WRAPPER_GEN_CFG_AN_LT_SEL_RX_MASK, 461294838Szbb AN_LT_WRAPPER_GEN_CFG_AN_LT_SEL_RX_SHIFT, 462294838Szbb AL_ETH_AN_LT_UNIT_32_BIT); 463294838Szbb AL_REG_FIELD_SET(cfg_lane_1, 464294838Szbb AN_LT_WRAPPER_GEN_CFG_AN_LT_SEL_TX_MASK, 465294838Szbb AN_LT_WRAPPER_GEN_CFG_AN_LT_SEL_TX_SHIFT, 466294838Szbb AL_ETH_AN_LT_UNIT_32_BIT); 467294838Szbb 468294838Szbb adapter->curr_lt_unit = AL_ETH_AN_LT_UNIT_32_BIT; 469294838Szbb 470294838Szbb break; 471294838Szbb default: 472294838Szbb al_err("%s: Unknown mac_mode\n", __func__); 473294838Szbb return; 474294838Szbb } 475294838Szbb 476294838Szbb al_reg_write32(&adapter->mac_regs_base->gen_v3.an_lt_0_addr, 477294838Szbb (uintptr_t)®s->gen.cfg); 478294838Szbb al_reg_write32(&adapter->mac_regs_base->gen_v3.an_lt_0_data, 479294838Szbb cfg_lane_0); 480294838Szbb 481294838Szbb al_reg_write32(&adapter->mac_regs_base->gen_v3.an_lt_1_addr, 482294838Szbb (uintptr_t)®s->gen.cfg); 483294838Szbb al_reg_write32(&adapter->mac_regs_base->gen_v3.an_lt_1_data, 484294838Szbb cfg_lane_1); 485294838Szbb 486294838Szbb al_reg_write32(&adapter->mac_regs_base->gen_v3.an_lt_2_addr, 487294838Szbb (uintptr_t)®s->gen.cfg); 488294838Szbb al_reg_write32(&adapter->mac_regs_base->gen_v3.an_lt_2_data, 489294838Szbb cfg_lane_2); 490294838Szbb 491294838Szbb al_reg_write32(&adapter->mac_regs_base->gen_v3.an_lt_3_addr, 492294838Szbb (uintptr_t)®s->gen.cfg); 493294838Szbb al_reg_write32(&adapter->mac_regs_base->gen_v3.an_lt_3_data, 494294838Szbb cfg_lane_3); 495294838Szbb} 496294838Szbb 497294838Szbbvoid al_eth_lp_coeff_up_get( 498294838Szbb struct al_hal_eth_adapter *adapter, 499294838Szbb enum al_eth_an_lt_lane lane, 500294838Szbb struct al_eth_kr_coef_up_data *lpcoeff) 501294838Szbb{ 502294838Szbb uint16_t reg; 503294838Szbb 504294838Szbb reg = al_eth_an_lt_reg_read(adapter, AL_ETH_KR_PMD_LP_COEF_UP, AL_ETH_LT_REGS, lane); 505294838Szbb 506294838Szbb lpcoeff->preset = 507294838Szbb (AL_REG_BIT_GET( 508294838Szbb reg, AL_ETH_KR_PMD_LP_COEF_UP_PRESET_SHIFT) != 0); 509294838Szbb 510294838Szbb lpcoeff->initialize = 511294838Szbb (AL_REG_BIT_GET( 512294838Szbb reg, AL_ETH_KR_PMD_LP_COEF_UP_INITIALIZE_SHIFT) != 0); 513294838Szbb 514294838Szbb lpcoeff->c_minus = AL_REG_FIELD_GET(reg, 515294838Szbb AL_ETH_KR_PMD_LP_COEF_UP_MINUS_MASK, 516294838Szbb AL_ETH_KR_PMD_LP_COEF_UP_MINUS_SHIFT); 517294838Szbb 518294838Szbb lpcoeff->c_zero = AL_REG_FIELD_GET(reg, 519294838Szbb AL_ETH_KR_PMD_LP_COEF_UP_ZERO_MASK, 520294838Szbb AL_ETH_KR_PMD_LP_COEF_UP_ZERO_SHIFT); 521294838Szbb 522294838Szbb lpcoeff->c_plus = AL_REG_FIELD_GET(reg, 523294838Szbb AL_ETH_KR_PMD_LP_COEF_UP_PLUS_MASK, 524294838Szbb AL_ETH_KR_PMD_LP_COEF_UP_PLUS_SHIFT); 525294838Szbb} 526294838Szbb 527294838Szbbvoid al_eth_lp_status_report_get( 528294838Szbb struct al_hal_eth_adapter *adapter, 529294838Szbb enum al_eth_an_lt_lane lane, 530294838Szbb struct al_eth_kr_status_report_data *status) 531294838Szbb{ 532294838Szbb uint16_t reg; 533294838Szbb 534294838Szbb reg = al_eth_an_lt_reg_read(adapter, AL_ETH_KR_PMD_LP_STATUS_REPORT, AL_ETH_LT_REGS, lane); 535294838Szbb 536294838Szbb status->c_minus = AL_REG_FIELD_GET(reg, 537294838Szbb AL_ETH_KR_PMD_LP_STATUS_REPORT_MINUS_MASK, 538294838Szbb AL_ETH_KR_PMD_LP_STATUS_REPORT_MINUS_SHIFT); 539294838Szbb 540294838Szbb status->c_zero = AL_REG_FIELD_GET(reg, 541294838Szbb AL_ETH_KR_PMD_LP_STATUS_REPORT_ZERO_MASK, 542294838Szbb AL_ETH_KR_PMD_LP_STATUS_REPORT_ZERO_SHIFT); 543294838Szbb 544294838Szbb status->c_plus = AL_REG_FIELD_GET(reg, 545294838Szbb AL_ETH_KR_PMD_LP_STATUS_REPORT_PLUS_MASK, 546294838Szbb AL_ETH_KR_PMD_LP_STATUS_REPORT_PLUS_SHIFT); 547294838Szbb 548294838Szbb status->receiver_ready = 549294838Szbb (AL_REG_BIT_GET( 550294838Szbb reg, AL_ETH_KR_PMD_LP_STATUS_RECEIVER_READY_SHIFT) != 0); 551294838Szbb 552294838Szbb} 553294838Szbb 554294838Szbbvoid al_eth_ld_coeff_up_set( 555294838Szbb struct al_hal_eth_adapter *adapter, 556294838Szbb enum al_eth_an_lt_lane lane, 557294838Szbb struct al_eth_kr_coef_up_data *ldcoeff) 558294838Szbb{ 559294838Szbb uint16_t reg = 0; 560294838Szbb 561294838Szbb if (ldcoeff->preset) 562294838Szbb AL_REG_BIT_SET(reg, AL_ETH_KR_PMD_LD_COEF_UP_PRESET_SHIFT); 563294838Szbb 564294838Szbb if (ldcoeff->initialize) 565294838Szbb AL_REG_BIT_SET(reg, AL_ETH_KR_PMD_LD_COEF_UP_INITIALIZE_SHIFT); 566294838Szbb 567294838Szbb AL_REG_FIELD_SET(reg, 568294838Szbb AL_ETH_KR_PMD_LD_COEF_UP_MINUS_MASK, 569294838Szbb AL_ETH_KR_PMD_LD_COEF_UP_MINUS_SHIFT, 570294838Szbb ldcoeff->c_minus); 571294838Szbb 572294838Szbb AL_REG_FIELD_SET(reg, 573294838Szbb AL_ETH_KR_PMD_LD_COEF_UP_ZERO_MASK, 574294838Szbb AL_ETH_KR_PMD_LD_COEF_UP_ZERO_SHIFT, 575294838Szbb ldcoeff->c_zero); 576294838Szbb 577294838Szbb AL_REG_FIELD_SET(reg, 578294838Szbb AL_ETH_KR_PMD_LD_COEF_UP_PLUS_MASK, 579294838Szbb AL_ETH_KR_PMD_LD_COEF_UP_PLUS_SHIFT, 580294838Szbb ldcoeff->c_plus); 581294838Szbb 582294838Szbb al_eth_an_lt_reg_write(adapter, AL_ETH_KR_PMD_LD_COEF_UP, AL_ETH_LT_REGS, lane, reg); 583294838Szbb} 584294838Szbb 585294838Szbbvoid al_eth_ld_status_report_set( 586294838Szbb struct al_hal_eth_adapter *adapter, 587294838Szbb enum al_eth_an_lt_lane lane, 588294838Szbb struct al_eth_kr_status_report_data *status) 589294838Szbb{ 590294838Szbb uint16_t reg = 0; 591294838Szbb 592294838Szbb AL_REG_FIELD_SET(reg, 593294838Szbb AL_ETH_KR_PMD_LD_STATUS_REPORT_MINUS_MASK, 594294838Szbb AL_ETH_KR_PMD_LD_STATUS_REPORT_MINUS_SHIFT, 595294838Szbb status->c_minus); 596294838Szbb 597294838Szbb AL_REG_FIELD_SET(reg, 598294838Szbb AL_ETH_KR_PMD_LD_STATUS_REPORT_ZERO_MASK, 599294838Szbb AL_ETH_KR_PMD_LD_STATUS_REPORT_ZERO_SHIFT, 600294838Szbb status->c_zero); 601294838Szbb 602294838Szbb AL_REG_FIELD_SET(reg, 603294838Szbb AL_ETH_KR_PMD_LD_STATUS_REPORT_PLUS_MASK, 604294838Szbb AL_ETH_KR_PMD_LD_STATUS_REPORT_PLUS_SHIFT, 605294838Szbb status->c_plus); 606294838Szbb 607294838Szbb if (status->receiver_ready) 608294838Szbb AL_REG_BIT_SET(reg, 609294838Szbb AL_ETH_KR_PMD_LD_STATUS_REPORT_RECEIVER_READY_SHIFT); 610294838Szbb 611294838Szbb al_eth_an_lt_reg_write(adapter, AL_ETH_KR_PMD_LD_STATUS_REPORT, AL_ETH_LT_REGS, lane, reg); 612294838Szbb} 613294838Szbb 614294838Szbbal_bool al_eth_kr_receiver_frame_lock_get(struct al_hal_eth_adapter *adapter, 615294838Szbb enum al_eth_an_lt_lane lane) 616294838Szbb{ 617294838Szbb uint16_t reg; 618294838Szbb 619294838Szbb reg = al_eth_an_lt_reg_read(adapter, AL_ETH_KR_PMD_STATUS, AL_ETH_LT_REGS, lane); 620294838Szbb 621294838Szbb return (AL_REG_BIT_GET(reg, 622294838Szbb AL_ETH_KR_PMD_STATUS_RECEIVER_FRAME_LOCK_SHIFT) != 0); 623294838Szbb} 624294838Szbb 625294838Szbbal_bool al_eth_kr_startup_proto_prog_get(struct al_hal_eth_adapter *adapter, 626294838Szbb enum al_eth_an_lt_lane lane) 627294838Szbb{ 628294838Szbb uint16_t reg; 629294838Szbb 630294838Szbb reg = al_eth_an_lt_reg_read(adapter, AL_ETH_KR_PMD_STATUS, AL_ETH_LT_REGS, lane); 631294838Szbb 632294838Szbb return (AL_REG_BIT_GET( 633294838Szbb reg, AL_ETH_KR_PMD_STATUS_RECEIVER_START_UP_PROTO_PROG_SHIFT) != 0); 634294838Szbb} 635294838Szbb 636294838Szbbal_bool al_eth_kr_training_status_fail_get(struct al_hal_eth_adapter *adapter, 637294838Szbb enum al_eth_an_lt_lane lane) 638294838Szbb{ 639294838Szbb uint16_t reg; 640294838Szbb 641294838Szbb reg = al_eth_an_lt_reg_read(adapter, AL_ETH_KR_PMD_STATUS, AL_ETH_LT_REGS, lane); 642294838Szbb 643294838Szbb return (AL_REG_BIT_GET(reg, AL_ETH_KR_PMD_STATUS_FAILURE_SHIFT) != 0); 644294838Szbb} 645294838Szbb 646294838Szbbvoid al_eth_receiver_ready_set(struct al_hal_eth_adapter *adapter, 647294838Szbb enum al_eth_an_lt_lane lane) 648294838Szbb{ 649294838Szbb al_eth_an_lt_reg_write(adapter, AL_ETH_KR_PMD_STATUS, AL_ETH_LT_REGS, lane, 1); 650294838Szbb} 651294838Szbb 652294838Szbb/*************************** auto negotiation *********************************/ 653294838Szbbstatic int al_eth_kr_an_validate_adv(struct al_hal_eth_adapter *adapter, 654294838Szbb struct al_eth_an_adv *an_adv) 655294838Szbb{ 656294838Szbb al_assert(adapter); 657294838Szbb 658294838Szbb if (an_adv == NULL) 659294838Szbb return 0; 660294838Szbb 661294838Szbb if (an_adv->selector_field != 1) { 662294838Szbb al_err("[%s]: %s failed on selector_field (%d)\n", 663294838Szbb adapter->name, __func__, an_adv->selector_field); 664294838Szbb return -EINVAL; 665294838Szbb } 666294838Szbb 667294838Szbb if (an_adv->capability & AL_BIT(2)) { 668294838Szbb al_err("[%s]: %s failed on capability bit 2 (%d)\n", 669294838Szbb adapter->name, __func__, an_adv->capability); 670294838Szbb return -EINVAL; 671294838Szbb } 672294838Szbb 673294838Szbb if (an_adv->remote_fault) { 674294838Szbb al_err("[%s]: %s failed on remote_fault (%d)\n", 675294838Szbb adapter->name, __func__, an_adv->remote_fault); 676294838Szbb return -EINVAL; 677294838Szbb } 678294838Szbb 679294838Szbb if (an_adv->acknowledge) { 680294838Szbb al_err("[%s]: %s failed on acknowledge (%d)\n", 681294838Szbb adapter->name, __func__, an_adv->acknowledge); 682294838Szbb return -EINVAL; 683294838Szbb } 684294838Szbb 685294838Szbb return 0; 686294838Szbb} 687294838Szbb 688294838Szbbstatic int al_eth_kr_an_write_adv(struct al_hal_eth_adapter *adapter, 689294838Szbb struct al_eth_an_adv *an_adv) 690294838Szbb{ 691294838Szbb uint16_t reg; 692294838Szbb 693294838Szbb if(an_adv == NULL) 694294838Szbb return 0; 695294838Szbb 696294838Szbb reg = 0; 697294838Szbb AL_REG_FIELD_SET(reg, AL_ETH_KR_AN_ADV1_SEL_FIELD_MASK, 698294838Szbb AL_ETH_KR_AN_ADV1_SEL_FIELD_SHIFT, 699294838Szbb an_adv->selector_field); 700294838Szbb 701294838Szbb AL_REG_FIELD_SET(reg, AL_ETH_KR_AN_ADV1_ECHOED_NONCE_MASK, 702294838Szbb AL_ETH_KR_AN_ADV1_ECHOED_NONCE_SHIFT, 703294838Szbb an_adv->echoed_nonce); 704294838Szbb 705294838Szbb AL_REG_FIELD_SET(reg, AL_ETH_KR_AN_ADV1_CAPABILITY_MASK, 706294838Szbb AL_ETH_KR_AN_ADV1_CAPABILITY_SHIFT, 707294838Szbb an_adv->capability); 708294838Szbb 709294838Szbb AL_REG_BIT_VAL_SET(reg, AL_ETH_KR_AN_ADV1_REM_FAULT_SHIFT, 710294838Szbb an_adv->remote_fault); 711294838Szbb 712294838Szbb AL_REG_BIT_VAL_SET(reg, AL_ETH_KR_AN_ADV1_ACK_SHIFT, 713294838Szbb an_adv->acknowledge); 714294838Szbb 715294838Szbb AL_REG_BIT_VAL_SET(reg, AL_ETH_KR_AN_ADV1_NEXT_PAGE_SHIFT, 716294838Szbb an_adv->next_page); 717294838Szbb 718294838Szbb al_eth_an_lt_reg_write(adapter, AL_ETH_KR_AN_ADV0, AL_ETH_AN_REGS, 719294838Szbb AL_ETH_AN__LT_LANE_0, reg); 720294838Szbb 721294838Szbb reg = 0; 722294838Szbb AL_REG_FIELD_SET(reg, AL_ETH_KR_AN_ADV2_TX_NONCE_MASK, 723294838Szbb AL_ETH_KR_AN_ADV2_TX_NONCE_SHIFT, 724294838Szbb an_adv->transmitted_nonce); 725294838Szbb 726294838Szbb AL_REG_FIELD_SET(reg, AL_ETH_KR_AN_ADV2_TECH_MASK, 727294838Szbb AL_ETH_KR_AN_ADV2_TECH_SHIFT, 728294838Szbb an_adv->technology); 729294838Szbb 730294838Szbb al_eth_an_lt_reg_write(adapter, AL_ETH_KR_AN_ADV1, AL_ETH_AN_REGS, 731294838Szbb AL_ETH_AN__LT_LANE_0, reg); 732294838Szbb 733294838Szbb reg = 0; 734294838Szbb AL_REG_FIELD_SET(reg, AL_ETH_KR_AN_ADV3_TECH_MASK, 735294838Szbb AL_ETH_KR_AN_ADV3_TECH_SHIFT, 736294838Szbb an_adv->technology >> 11); 737294838Szbb 738294838Szbb AL_REG_FIELD_SET(reg, AL_ETH_KR_AN_ADV3_FEC_MASK, 739294838Szbb AL_ETH_KR_AN_ADV3_FEC_SHIFT, 740294838Szbb an_adv->fec_capability); 741294838Szbb 742294838Szbb al_eth_an_lt_reg_write(adapter, AL_ETH_KR_AN_ADV2, AL_ETH_AN_REGS, 743294838Szbb AL_ETH_AN__LT_LANE_0, reg); 744294838Szbb 745294838Szbb return 0; 746294838Szbb} 747294838Szbb 748294838Szbbvoid al_eth_kr_an_read_adv(struct al_hal_eth_adapter *adapter, 749294838Szbb struct al_eth_an_adv *an_adv) 750294838Szbb{ 751294838Szbb int16_t reg; 752294838Szbb 753294838Szbb al_assert(an_adv != NULL); 754294838Szbb 755294838Szbb 756294838Szbb reg = al_eth_an_lt_reg_read(adapter, AL_ETH_KR_AN_REM_ADV0, 757294838Szbb AL_ETH_AN_REGS, AL_ETH_AN__LT_LANE_0); 758294838Szbb 759294838Szbb an_adv->selector_field = AL_REG_FIELD_GET(reg, 760294838Szbb AL_ETH_KR_AN_ADV1_SEL_FIELD_MASK, 761294838Szbb AL_ETH_KR_AN_ADV1_SEL_FIELD_SHIFT); 762294838Szbb 763294838Szbb an_adv->echoed_nonce = AL_REG_FIELD_GET(reg, 764294838Szbb AL_ETH_KR_AN_ADV1_ECHOED_NONCE_MASK, 765294838Szbb AL_ETH_KR_AN_ADV1_ECHOED_NONCE_SHIFT); 766294838Szbb 767294838Szbb an_adv->capability = AL_REG_FIELD_GET(reg, 768294838Szbb AL_ETH_KR_AN_ADV1_CAPABILITY_MASK, 769294838Szbb AL_ETH_KR_AN_ADV1_CAPABILITY_SHIFT); 770294838Szbb 771294838Szbb an_adv->remote_fault = AL_REG_BIT_GET(reg, 772294838Szbb AL_ETH_KR_AN_ADV1_REM_FAULT_SHIFT); 773294838Szbb 774294838Szbb an_adv->acknowledge = AL_REG_BIT_GET(reg, 775294838Szbb AL_ETH_KR_AN_ADV1_ACK_SHIFT); 776294838Szbb 777294838Szbb an_adv->next_page = AL_REG_BIT_GET(reg, 778294838Szbb AL_ETH_KR_AN_ADV1_NEXT_PAGE_SHIFT); 779294838Szbb 780294838Szbb 781294838Szbb reg = al_eth_an_lt_reg_read(adapter, AL_ETH_KR_AN_REM_ADV1, 782294838Szbb AL_ETH_AN_REGS, AL_ETH_AN__LT_LANE_0); 783294838Szbb 784294838Szbb an_adv->transmitted_nonce = AL_REG_FIELD_GET(reg, 785294838Szbb AL_ETH_KR_AN_ADV2_TX_NONCE_MASK, 786294838Szbb AL_ETH_KR_AN_ADV2_TX_NONCE_SHIFT); 787294838Szbb 788294838Szbb an_adv->technology = AL_REG_FIELD_GET(reg, 789294838Szbb AL_ETH_KR_AN_ADV2_TECH_MASK, 790294838Szbb AL_ETH_KR_AN_ADV2_TECH_SHIFT); 791294838Szbb 792294838Szbb 793294838Szbb reg = al_eth_an_lt_reg_read(adapter, AL_ETH_KR_AN_REM_ADV2, 794294838Szbb AL_ETH_AN_REGS, AL_ETH_AN__LT_LANE_0); 795294838Szbb 796294838Szbb an_adv->technology |= (AL_REG_FIELD_GET(reg, 797294838Szbb AL_ETH_KR_AN_ADV3_TECH_MASK, 798294838Szbb AL_ETH_KR_AN_ADV3_TECH_SHIFT) << 11); 799294838Szbb 800294838Szbb an_adv->fec_capability = AL_REG_FIELD_GET(reg, 801294838Szbb AL_ETH_KR_AN_ADV3_FEC_MASK, 802294838Szbb AL_ETH_KR_AN_ADV3_FEC_SHIFT); 803294838Szbb} 804294838Szbb 805294838Szbbint al_eth_kr_next_page_read(struct al_hal_eth_adapter *adapter, 806294838Szbb struct al_eth_an_np *np) 807294838Szbb{ 808294838Szbb uint16_t reg; 809294838Szbb 810294838Szbb reg = al_eth_an_lt_reg_read(adapter, 811294838Szbb AL_ETH_KR_AN_REM_XNP_ADV0, 812294838Szbb AL_ETH_AN_REGS, 813294838Szbb AL_ETH_AN__LT_LANE_0); 814294838Szbb 815294838Szbb np->unformatted_code_field = AL_REG_FIELD_GET(reg, AL_ETH_KR_AN_NP_ADV1_DATA1_MASK, 816294838Szbb AL_ETH_KR_AN_NP_ADV1_DATA1_SHIFT); 817294838Szbb 818294838Szbb np->toggle = AL_REG_FIELD_GET(reg, AL_ETH_KR_AN_NP_ADV1_TOGGLE_MASK, 819294838Szbb AL_ETH_KR_AN_NP_ADV1_TOGGLE_SHIFT); 820294838Szbb 821294838Szbb np->ack2 = AL_REG_FIELD_GET(reg, AL_ETH_KR_AN_NP_ADV1_ACK2_MASK, 822294838Szbb AL_ETH_KR_AN_NP_ADV1_ACK2_SHIFT); 823294838Szbb 824294838Szbb np->msg_page = AL_REG_FIELD_GET(reg, AL_ETH_KR_AN_NP_ADV1_MSG_PAGE_MASK, 825294838Szbb AL_ETH_KR_AN_NP_ADV1_MSG_PAGE_SHIFT); 826294838Szbb 827294838Szbb np->next_page = AL_REG_FIELD_GET(reg, AL_ETH_KR_AN_NP_ADV1_NP_MASK, 828294838Szbb AL_ETH_KR_AN_NP_ADV1_NP_SHIFT); 829294838Szbb 830294838Szbb np->unformatted_code_field1 = al_eth_an_lt_reg_read(adapter, 831294838Szbb AL_ETH_KR_AN_REM_XNP_ADV1, 832294838Szbb AL_ETH_AN_REGS, 833294838Szbb AL_ETH_AN__LT_LANE_0); 834294838Szbb np->unformatted_code_field2 = al_eth_an_lt_reg_read(adapter, 835294838Szbb AL_ETH_KR_AN_REM_XNP_ADV2, 836294838Szbb AL_ETH_AN_REGS, 837294838Szbb AL_ETH_AN__LT_LANE_0); 838294838Szbb 839294838Szbb return 0; 840294838Szbb} 841294838Szbb 842294838Szbbint al_eth_kr_next_page_write(struct al_hal_eth_adapter *adapter, 843294838Szbb struct al_eth_an_np *np) 844294838Szbb{ 845294838Szbb uint16_t reg = 0; 846294838Szbb 847294838Szbb AL_REG_FIELD_SET(reg, AL_ETH_KR_AN_NP_ADV1_DATA1_MASK, 848294838Szbb AL_ETH_KR_AN_NP_ADV1_DATA1_SHIFT, 849294838Szbb np->unformatted_code_field); 850294838Szbb AL_REG_FIELD_SET(reg, AL_ETH_KR_AN_NP_ADV1_TOGGLE_MASK, 851294838Szbb AL_ETH_KR_AN_NP_ADV1_TOGGLE_SHIFT, 852294838Szbb np->toggle); 853294838Szbb AL_REG_FIELD_SET(reg, AL_ETH_KR_AN_NP_ADV1_ACK2_MASK, 854294838Szbb AL_ETH_KR_AN_NP_ADV1_ACK2_SHIFT, 855294838Szbb np->ack2); 856294838Szbb AL_REG_FIELD_SET(reg, AL_ETH_KR_AN_NP_ADV1_MSG_PAGE_MASK, 857294838Szbb AL_ETH_KR_AN_NP_ADV1_MSG_PAGE_SHIFT, 858294838Szbb np->msg_page); 859294838Szbb AL_REG_FIELD_SET(reg, AL_ETH_KR_AN_NP_ADV1_NP_MASK, 860294838Szbb AL_ETH_KR_AN_NP_ADV1_NP_SHIFT, 861294838Szbb np->next_page); 862294838Szbb 863294838Szbb al_eth_an_lt_reg_write(adapter, AL_ETH_KR_AN_XNP_ADV0, AL_ETH_AN_REGS, 864294838Szbb AL_ETH_AN__LT_LANE_0, reg); 865294838Szbb 866294838Szbb al_eth_an_lt_reg_write(adapter, AL_ETH_KR_AN_XNP_ADV1, AL_ETH_AN_REGS, 867294838Szbb AL_ETH_AN__LT_LANE_0, np->unformatted_code_field1); 868294838Szbb al_eth_an_lt_reg_write(adapter, AL_ETH_KR_AN_XNP_ADV2, AL_ETH_AN_REGS, 869294838Szbb AL_ETH_AN__LT_LANE_0, np->unformatted_code_field2); 870294838Szbb 871294838Szbb return 0; 872294838Szbb} 873294838Szbb 874294838Szbbint al_eth_kr_an_init(struct al_hal_eth_adapter *adapter, 875294838Szbb struct al_eth_an_adv *an_adv) 876294838Szbb{ 877294838Szbb int rc; 878294838Szbb 879294838Szbb if (adapter->rev_id > AL_ETH_REV_ID_2) 880294838Szbb al_eth_an_lt_unit_config(adapter); 881294838Szbb 882294838Szbb rc = al_eth_kr_an_validate_adv(adapter, an_adv); 883294838Szbb if (rc) 884294838Szbb return rc; 885294838Szbb 886294838Szbb rc = al_eth_kr_an_write_adv(adapter, an_adv); 887294838Szbb if (rc) 888294838Szbb return rc; 889294838Szbb 890294838Szbb /* clear status */ 891294838Szbb al_eth_an_lt_reg_read(adapter, AL_ETH_KR_AN_STATUS, AL_ETH_AN_REGS, AL_ETH_AN__LT_LANE_0); 892294838Szbb 893294838Szbb al_dbg("[%s]: autonegotiation initialized successfully", adapter->name); 894294838Szbb return 0; 895294838Szbb} 896294838Szbb 897294838Szbbint al_eth_kr_an_start(struct al_hal_eth_adapter *adapter, 898294838Szbb enum al_eth_an_lt_lane lane, 899294838Szbb al_bool next_page_enable, 900294838Szbb al_bool lt_enable) 901294838Szbb{ 902294838Szbb uint16_t control = AL_ETH_KR_AN_CONTROL_ENABLE | AL_ETH_KR_AN_CONTROL_RESTART; 903294838Szbb 904294838Szbb al_dbg("Eth [%s]: enable autonegotiation. lt_en %s", 905294838Szbb adapter->name, (lt_enable == AL_TRUE) ? "yes" : "no"); 906294838Szbb 907294838Szbb al_eth_an_lt_reg_write(adapter, AL_ETH_KR_PMD_CONTROL, AL_ETH_LT_REGS, 908294838Szbb lane, AL_BIT(AL_ETH_KR_PMD_CONTROL_RESTART)); 909294838Szbb 910294838Szbb if (next_page_enable == AL_TRUE) 911294838Szbb control |= AL_ETH_KR_AN_CONTROL_NP_ENABLE; 912294838Szbb 913294838Szbb al_eth_an_lt_reg_write(adapter, AL_ETH_KR_AN_CONTROL, AL_ETH_AN_REGS, 914294838Szbb lane, control); 915294838Szbb 916294838Szbb if (lt_enable == AL_TRUE) { 917294838Szbb al_eth_kr_lt_initialize(adapter, lane); 918294838Szbb } 919294838Szbb 920294838Szbb return 0; 921294838Szbb} 922294838Szbb 923294838Szbbvoid al_eth_kr_an_stop(struct al_hal_eth_adapter *adapter) 924294838Szbb{ 925294838Szbb al_eth_an_lt_reg_write(adapter, AL_ETH_KR_AN_CONTROL, AL_ETH_AN_REGS, 926294838Szbb AL_ETH_AN__LT_LANE_0, 0); 927294838Szbb} 928294838Szbb 929294838Szbbvoid al_eth_kr_an_status_check(struct al_hal_eth_adapter *adapter, 930294838Szbb al_bool *page_received, 931294838Szbb al_bool *an_completed, 932294838Szbb al_bool *error) 933294838Szbb{ 934294838Szbb uint16_t reg; 935294838Szbb 936294838Szbb reg = al_eth_an_lt_reg_read(adapter, AL_ETH_KR_AN_STATUS, 937294838Szbb AL_ETH_AN_REGS, AL_ETH_AN__LT_LANE_0); 938294838Szbb 939294838Szbb if ((reg & AL_ETH_KR_AN_STATUS_CHECK_MASK) != 940294838Szbb AL_ETH_KR_AN_STATUS_CHECK_NO_ERROR) { 941294838Szbb al_err("[%s]: %s AN_STATUS (0x%x) indicated error\n", 942294838Szbb adapter->name, __func__, reg); 943294838Szbb 944294838Szbb *error = AL_TRUE; 945294838Szbb } 946294838Szbb 947294838Szbb if (reg & AL_ETH_KR_AN_STATUS_BASE_PAGE_RECEIVED) 948294838Szbb *page_received = AL_TRUE; 949294838Szbb else 950294838Szbb *page_received = AL_FALSE; 951294838Szbb 952294838Szbb if (reg & AL_ETH_KR_AN_STATUS_COMPLETED) 953294838Szbb *an_completed = AL_TRUE; 954294838Szbb else 955294838Szbb *an_completed = AL_FALSE; 956294838Szbb} 957294838Szbb 958294838Szbb 959294838Szbb/****************************** KR Link Training *****************************/ 960294838Szbbvoid al_eth_kr_lt_restart(struct al_hal_eth_adapter *adapter, 961294838Szbb enum al_eth_an_lt_lane lane) 962294838Szbb{ 963294838Szbb al_dbg("[%s]: KR LT Restart Link Training.\n", adapter->name); 964294838Szbb 965294838Szbb al_eth_an_lt_reg_write(adapter, AL_ETH_KR_PMD_CONTROL, AL_ETH_LT_REGS, 966294838Szbb lane, (AL_BIT(AL_ETH_KR_PMD_CONTROL_ENABLE) | 967294838Szbb AL_BIT(AL_ETH_KR_PMD_CONTROL_RESTART))); 968294838Szbb} 969294838Szbb 970294838Szbbvoid al_eth_kr_lt_stop(struct al_hal_eth_adapter *adapter, 971294838Szbb enum al_eth_an_lt_lane lane) 972294838Szbb{ 973294838Szbb al_dbg("[%s]: KR LT Stop Link Training.\n", adapter->name); 974294838Szbb 975294838Szbb al_eth_an_lt_reg_write(adapter, AL_ETH_KR_PMD_CONTROL, AL_ETH_LT_REGS, 976294838Szbb lane, AL_BIT(AL_ETH_KR_PMD_CONTROL_RESTART)); 977294838Szbb} 978294838Szbb 979294838Szbbvoid al_eth_kr_lt_initialize(struct al_hal_eth_adapter *adapter, 980294838Szbb enum al_eth_an_lt_lane lane) 981294838Szbb{ 982294838Szbb al_dbg("[%s]: KR LT Initialize.\n", adapter->name); 983294838Szbb 984294838Szbb /* Reset LT state machine */ 985294838Szbb al_eth_kr_lt_stop(adapter, lane); 986294838Szbb 987294838Szbb /* clear receiver status */ 988294838Szbb al_eth_an_lt_reg_write(adapter, AL_ETH_KR_PMD_STATUS, AL_ETH_LT_REGS, lane, 0); 989294838Szbb 990294838Szbb /* Coefficient Update to all zero (no command, hold) */ 991294838Szbb al_eth_an_lt_reg_write(adapter, AL_ETH_KR_PMD_LD_COEF_UP, AL_ETH_LT_REGS, lane, 0); 992294838Szbb /* Coefficient Status to all zero (not_updated) */ 993294838Szbb al_eth_an_lt_reg_write(adapter, AL_ETH_KR_PMD_LD_STATUS_REPORT, AL_ETH_LT_REGS, lane, 0); 994294838Szbb 995294838Szbb /* start */ 996294838Szbb al_eth_kr_lt_restart(adapter, lane); 997294838Szbb} 998294838Szbb 999294838Szbbal_bool al_eth_kr_lt_frame_lock_wait(struct al_hal_eth_adapter *adapter, 1000294838Szbb enum al_eth_an_lt_lane lane, 1001294838Szbb uint32_t timeout) 1002294838Szbb{ 1003294838Szbb uint32_t loop; 1004294838Szbb uint16_t reg = 0; 1005294838Szbb 1006294838Szbb for (loop = 0; loop < timeout; loop++) { 1007294838Szbb reg = al_eth_an_lt_reg_read(adapter, AL_ETH_KR_PMD_STATUS, AL_ETH_LT_REGS, lane); 1008294838Szbb 1009294838Szbb if (AL_REG_BIT_GET(reg, AL_ETH_KR_PMD_STATUS_FAILURE_SHIFT)) { 1010294838Szbb al_info("[%s]: Failed on Training Failure." 1011294838Szbb " loops %d PMD STATUS 0x%04x\n", 1012294838Szbb adapter->name, loop, reg); 1013294838Szbb 1014294838Szbb return AL_FALSE; 1015294838Szbb } 1016294838Szbb if (AL_REG_BIT_GET(reg, 1017294838Szbb AL_ETH_KR_PMD_STATUS_RECEIVER_FRAME_LOCK_SHIFT)) { 1018294838Szbb al_dbg("[%s]: Frame lock received." 1019294838Szbb " loops %d PMD STATUS 0x%04x\n", 1020294838Szbb adapter->name, loop, reg); 1021294838Szbb 1022294838Szbb return AL_TRUE; 1023294838Szbb } 1024294838Szbb al_udelay(1); 1025294838Szbb } 1026294838Szbb al_info("[%s]: Failed on timeout. PMD STATUS 0x%04x\n", 1027294838Szbb adapter->name, reg); 1028294838Szbb 1029294838Szbb return AL_FALSE; 1030294838Szbb} 1031