1 /******************************************************************************* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 * 21 * Copyright 2014 QLogic Corporation 22 * The contents of this file are subject to the terms of the 23 * QLogic End User License (the "License"). 24 * You may not use this file except in compliance with the License. 25 * 26 * You can obtain a copy of the License at 27 * http://www.qlogic.com/Resources/Documents/DriverDownloadHelp/ 28 * QLogic_End_User_Software_License.txt 29 * See the License for the specific language governing permissions 30 * and limitations under the License. 31 * 32 * 33 * Module Description: 34 * This file contains functions that handle direct HW access 35 * 36 ******************************************************************************/ 37 38 #include "lm5710.h" 39 #include "hw_dump.h" 40 #include "577xx_int_offsets.h" 41 42 /* not in hsi */ 43 void ecore_init_cmng(const struct cmng_init_input *input_data, 44 struct cmng_init *ram_data); 45 46 void ecore_init_max_per_vn(u16_t vnic_max_rate, 47 struct rate_shaping_vars_per_vn *ram_data); 48 49 /*The NIG mirror is only used in VMChimney in MF/SI mode. 50 In this mode, we assume that the driver in the host OS loads 51 first, and allocates offset 0 in the NIG for it's own MAC address, 52 so we don't use it. Also, iSCSI has a reserved entry in the NIG, so 53 we don't use that either. 54 */ 55 #define IS_VALID_NIG_IDX(_idx) ((_idx != ECORE_LLH_CAM_ETH_LINE) && (_idx != ECORE_LLH_CAM_ISCSI_ETH_LINE)) 56 #define INVALID_NIG_OFFSET ((u8_t)-1) 57 58 // initialize congestion managmet params 59 void lm_cmng_init(struct _lm_device_t *pdev, u32_t port_rate) 60 { 61 u8_t vnic = 0; 62 u32_t i = 0; 63 u32_t* buf = NULL; 64 u8_t all_zero = 0; 65 u8_t num_vnics = pdev->params.vnics_per_port; 66 const u8_t b_afex_and_non_pmf = IS_MF_AFEX_MODE(pdev) && (!IS_PMF(pdev)); 67 const u8_t port_id = PORT_ID(pdev); // TBD: E1H - cmng params are currently per port, may change to be per function 68 const u8_t vnic_id = VNIC_ID(pdev); 69 static const u8_t DEF_MIN_RATE = 1 ; /* default MIN rate in case VNIC min rate is configured to zero- 100Mbps */ 70 struct cmng_init_input input_data = {0}; 71 struct cmng_init ram_data = {{{0}}}; 72 73 if(IS_MULTI_VNIC(pdev) && pdev->params.cmng_enable) 74 { 75 SET_FLAGS(input_data.flags.cmng_enables, CMNG_FLAGS_PER_PORT_RATE_SHAPING_VN); 76 input_data.port_rate = port_rate; 77 78 all_zero = TRUE; 79 for (vnic = 0 ; vnic < num_vnics ; vnic++) 80 { 81 input_data.vnic_max_rate[vnic] = lm_get_max_bw(pdev, 82 port_rate, 83 vnic); 84 85 if (!GET_FLAGS(pdev->hw_info.mf_info.func_mf_cfg , FUNC_MF_CFG_FUNC_HIDE)) 86 { 87 if (pdev->hw_info.mf_info.min_bw[vnic] == 0) 88 { 89 input_data.vnic_min_rate[vnic] = DEF_MIN_RATE; 90 } 91 else 92 { 93 input_data.vnic_min_rate[vnic] = pdev->hw_info.mf_info.min_bw[vnic]; 94 all_zero = FALSE; 95 } 96 } 97 } 98 99 // IS_DCB_ENABLED isn't updated when this function is called from lm_init_intmem_port 100 // but it is called each time the link is up. 101 if (!(all_zero || LM_DCBX_ETS_IS_ENABLED(pdev))) 102 { 103 SET_FLAGS(input_data.flags.cmng_enables,CMNG_FLAGS_PER_PORT_FAIRNESS_VN); 104 } 105 106 if( b_afex_and_non_pmf ) 107 { 108 ecore_init_max_per_vn( input_data.vnic_max_rate[vnic_id], &ram_data.vnic.vnic_max_rate[vnic_id] ); 109 } 110 else 111 { 112 ecore_init_cmng(&input_data,&ram_data); 113 } 114 } 115 116 // store per vnic struct to internal memory rs. we store data for all 4 vnics even if there are only 2 vnics, just to 117 // make sure there are known values. 118 for (vnic = 0; vnic < ARRSIZE(ram_data.vnic.vnic_max_rate); vnic++) 119 { 120 buf = (u32_t *)&ram_data.vnic.vnic_max_rate[vnic]; 121 ASSERT_STATIC(0 == sizeof(ram_data.vnic.vnic_max_rate[vnic]) % 4); 122 123 if( b_afex_and_non_pmf && (vnic != vnic_id) ) 124 { 125 // If AFEX && non pmf we want to write only for the current VNIC 126 continue; 127 } 128 129 for (i = 0; i < sizeof(ram_data.vnic.vnic_max_rate[vnic])/4; i++) 130 { 131 LM_INTMEM_WRITE32(pdev,XSTORM_RATE_SHAPING_PER_VN_VARS_OFFSET((port_id+2*vnic))+i*4, 132 buf[i], BAR_XSTRORM_INTMEM); 133 } 134 } 135 136 if( b_afex_and_non_pmf ) 137 { 138 // If AFEX && non pmf we want to write only for the current VNIC 139 // All other writes below are for PMF so we exit in this case. 140 return; 141 } 142 143 // Store per port struct to internal memory 144 buf = (u32_t *)&ram_data.port.rs_vars; 145 ASSERT_STATIC(0 == (sizeof(ram_data.port.rs_vars) % 4)) ; 146 for (i = 0; i < sizeof(ram_data.port.rs_vars)/4; i++) 147 { 148 LM_INTMEM_WRITE32(pdev,(XSTORM_CMNG_PER_PORT_VARS_OFFSET(port_id) + OFFSETOF(struct cmng_struct_per_port, rs_vars) + i*4), 149 buf[i], BAR_XSTRORM_INTMEM); 150 } 151 152 buf = (u32_t *)&ram_data.port.fair_vars; 153 ASSERT_STATIC(0 == (sizeof(ram_data.port.fair_vars) % 4)) ; 154 for (i = 0; i < sizeof(ram_data.port.fair_vars)/4; i++) 155 { 156 LM_INTMEM_WRITE32(pdev,(XSTORM_CMNG_PER_PORT_VARS_OFFSET(port_id) + OFFSETOF(struct cmng_struct_per_port, fair_vars) + i*4), 157 buf[i], BAR_XSTRORM_INTMEM); 158 } 159 160 buf = (u32_t *)&ram_data.port.flags; 161 ASSERT_STATIC(0 == (sizeof(ram_data.port.flags) % 4)); 162 for (i = 0; i < sizeof(ram_data.port.flags)/4; i++) 163 { 164 LM_INTMEM_WRITE32(pdev,(XSTORM_CMNG_PER_PORT_VARS_OFFSET(port_id) + OFFSETOF(struct cmng_struct_per_port, flags) + i*4), 165 buf[i], BAR_XSTRORM_INTMEM); 166 } 167 168 // store per vnic struct to internal memory fair. we store data for all 4 vnics even if there are only 2 vnics, just to 169 //make sure there are known values. 170 for (vnic = 0; vnic < ARRSIZE(ram_data.vnic.vnic_min_rate); vnic++) 171 { 172 buf = (u32_t *)&ram_data.vnic.vnic_min_rate[vnic]; 173 ASSERT_STATIC(0 == sizeof(ram_data.vnic.vnic_min_rate[vnic]) % 4); 174 for (i = 0; i < sizeof(ram_data.vnic.vnic_min_rate[vnic])/4; i++) 175 { 176 LM_INTMEM_WRITE32(pdev,XSTORM_FAIRNESS_PER_VN_VARS_OFFSET((port_id+2*vnic))+i*4, 177 buf[i], BAR_XSTRORM_INTMEM); 178 } 179 } 180 181 } /* lm_cmng_init */ 182 183 /**initialize_nig_entry 184 * Initialize a NIG mirror entry to a given MAC address. Note - 185 * the entrie's reference count remains 0. 186 * 187 * @param pdev 188 * @param offset the index of the NIG entry 189 * @param addr the MAC address to use 190 * 191 * @return lm_status_t LM_STATUS_SUCCESS on success, some other 192 * failure code on failure. 193 */ 194 static lm_status_t lm_initialize_nig_entry( 195 lm_device_t *pdev, 196 u8_t offset, 197 u8_t *addr) 198 { 199 lm_nig_mirror_entry_t* entry = &pdev->vars.nig_mirror.entries[offset]; 200 DbgBreakIf(entry->refcnt != 0); 201 mm_memcpy(entry->addr, addr, ARRSIZE(entry->addr)); 202 return LM_STATUS_SUCCESS; 203 } 204 205 /**get_available_nig_entry 206 * Find a NIG entry that's not in use. Entry 0 and 15 are never 207 * considered available, since they are used by iSCSI and by the 208 * L2 client. 209 * 210 * @param pdev 211 * 212 * @return an index to a usable NIG entry, or INVALID_NIG_OFFSET 213 * if there aren't any available entries. 214 */ 215 static u8_t lm_get_available_nig_entry(lm_device_t *pdev) 216 { 217 u8_t i; 218 lm_nig_mirror_t *nig_mirror = &pdev->vars.nig_mirror; 219 220 for (i=0; i<ARRSIZE(nig_mirror->entries); ++i) 221 { 222 if (IS_VALID_NIG_IDX(i) && 223 (nig_mirror->entries[i].refcnt == 0)) 224 { 225 return i; 226 } 227 } 228 return INVALID_NIG_OFFSET; 229 } 230 231 /**find_nig_entry_for_addr 232 * Find the entry for a given MAC address in the nig. 233 * 234 * @param pdev 235 * @param addr the MAC address to look for 236 * 237 * @return u8_t the index of the NIG entry that contains the 238 * given MAC address, or INVALID_NIG_OFFSET if no such 239 * entry exists. 240 */ 241 static u8_t lm_find_nig_entry_for_addr( 242 lm_device_t *pdev, 243 u8_t *addr) 244 { 245 u8_t i; 246 lm_nig_mirror_t *nig_mirror = &pdev->vars.nig_mirror; 247 lm_nig_mirror_entry_t* cur_entry = NULL; 248 249 for (i=0; i<ARRSIZE(nig_mirror->entries); ++i) 250 { 251 cur_entry = &nig_mirror->entries[i]; 252 if ( (cur_entry->refcnt > 0) && 253 (mm_memcmp(cur_entry->addr, addr, ARRSIZE(cur_entry->addr))) ) 254 { 255 return i; 256 } 257 } 258 return INVALID_NIG_OFFSET; 259 } 260 261 lm_status_t lm_insert_nig_entry( 262 lm_device_t *pdev, 263 u8_t *addr) 264 { 265 u8_t offset = 0; 266 lm_status_t lm_status = LM_STATUS_SUCCESS; 267 268 offset = lm_find_nig_entry_for_addr(pdev, addr); 269 270 if (offset == INVALID_NIG_OFFSET) 271 { 272 /*If there was no entry for this MAC, insert it to an available slot and call lm_set_mac_in_nig.*/ 273 offset = lm_get_available_nig_entry(pdev); 274 if (offset == INVALID_NIG_OFFSET) 275 { 276 return LM_STATUS_RESOURCE; //no available NIG entry. 277 } 278 279 lm_status = lm_initialize_nig_entry(pdev, offset, addr); 280 DbgBreakIf (lm_status != LM_STATUS_SUCCESS); 281 282 lm_status = lm_set_mac_in_nig(pdev, addr, LM_CLI_IDX_NDIS, offset); 283 if (lm_status != LM_STATUS_SUCCESS) 284 { 285 return lm_status; 286 } 287 } 288 289 NIG_ENTRY_INC_REFCNT(&pdev->vars.nig_mirror.entries[offset]); 290 291 return lm_status; 292 } 293 294 /**remove_nig_entry 295 * Dereference the entry for a given MAC address. If this was 296 * the last reference the MAC address is removed from the NIG. 297 * 298 * @param pdev 299 * @param addr the MAC address 300 * 301 * @return lm_status_t LM_STATUS_SUCCESS on success, 302 * LM_STATUS_FAILURE if the given MAC is not in the NIG, 303 * other failure codes on other errors. 304 */ 305 lm_status_t lm_remove_nig_entry( 306 lm_device_t *pdev, 307 u8_t *addr) 308 { 309 u8_t offset = 0; 310 lm_status_t lm_status = LM_STATUS_SUCCESS; 311 lm_nig_mirror_entry_t* entry = NULL; 312 313 offset = lm_find_nig_entry_for_addr(pdev, addr); 314 if (offset == INVALID_NIG_OFFSET) 315 { 316 DbgBreakIf(offset == INVALID_NIG_OFFSET); //trying to remove an address that isn't in the NIG. 317 return LM_STATUS_FAILURE; 318 } 319 320 entry = &pdev->vars.nig_mirror.entries[offset]; 321 322 NIG_ENTRY_DEC_REFCNT(entry); 323 324 if (entry->refcnt == 0) 325 { 326 lm_status = lm_set_mac_in_nig(pdev, NULL, LM_CLI_IDX_NDIS, offset); 327 if (lm_status != LM_STATUS_SUCCESS) 328 { 329 return lm_status; 330 } 331 mm_mem_zero(entry->addr, sizeof(entry->addr)); 332 } 333 334 return lm_status; 335 } 336 337 void lm_setup_fan_failure_detection(struct _lm_device_t *pdev) 338 { 339 u32_t val = 0; 340 lm_status_t lm_status = LM_STATUS_SUCCESS; 341 u8_t port = 0; 342 u8_t is_required = FALSE; 343 u32 offset = 0; 344 345 offset = OFFSETOF(shmem_region_t, dev_info.shared_hw_config.config2) ; 346 347 LM_SHMEM_READ(pdev, offset, &val); 348 349 val &= SHARED_HW_CFG_FAN_FAILURE_MASK; 350 351 switch(val) 352 { 353 case SHARED_HW_CFG_FAN_FAILURE_PHY_TYPE: 354 { 355 /* 356 * The fan failure mechanism is usually related to the PHY type since 357 * the power consumption of the board is effected by the PHY. Currently, 358 * fan is required for most designs with SFX7101, BCM8727 and BCM8481. 359 */ 360 for (port = PORT_0; port < PORT_MAX; port++) 361 { 362 is_required |= elink_fan_failure_det_req(pdev, pdev->hw_info.shmem_base, pdev->hw_info.shmem_base2, port); 363 } 364 } 365 break; 366 367 case SHARED_HW_CFG_FAN_FAILURE_ENABLED: 368 is_required = TRUE; 369 break; 370 371 case SHARED_HW_CFG_FAN_FAILURE_DISABLED: 372 default: 373 break; 374 } 375 376 DbgMessage(pdev, WARN, "lm_setup_fan_failure_detection: cfg=0x%x is_required=%d\n", val, is_required ); 377 378 if (!is_required) 379 { 380 return; 381 } 382 383 // read spio5 in order to make it input collaterally - we don't care of the returned value 384 // MCP does the same 385 lm_status = lm_spio_read( pdev, 5, &val ) ; 386 if( LM_STATUS_SUCCESS != lm_status ) 387 { 388 DbgBreakIf(1) ; 389 } 390 391 // We write here since value changes from 1 to 0 392 val = REG_RD(pdev,MISC_REG_SPIO_INT) ; 393 val |= (1<<(16+5)) ; 394 REG_WR(pdev,MISC_REG_SPIO_INT, val ) ; 395 396 // enable the SPIO_INT 5 to signal the IGU 397 val = REG_RD(pdev,MISC_REG_SPIO_EVENT_EN) ; 398 val |= (1<<5) ; 399 REG_WR(pdev,MISC_REG_SPIO_EVENT_EN, val ) ; 400 } 401 402 /* 403 *------------------------------------------------------------------------ 404 * lm_gpio_read - 405 * 406 * Read the value of the requested GPIO pin (with pin_num) 407 * 408 *------------------------------------------------------------------------ 409 */ 410 lm_status_t lm_gpio_read(struct _lm_device_t *pdev, u32_t pin_num, u32_t* value_ptr, u8_t port) 411 { 412 u32_t reg_val = 0; 413 u32_t gpio_port = 0; 414 u32_t mask = 0; 415 u32_t swap_val = 0; 416 u32_t swap_override = 0; 417 418 if ( CHK_NULL(pdev) || CHK_NULL(value_ptr) ) 419 { 420 DbgBreakIf(!pdev); 421 DbgBreakIf(!value_ptr); 422 return LM_STATUS_INVALID_PARAMETER ; 423 } 424 425 if (pin_num > MISC_REGISTERS_GPIO_3) 426 { 427 DbgMessage(pdev, FATAL , "Invalid pin_num GPIO %d\n", pin_num); 428 return LM_STATUS_INVALID_PARAMETER; 429 } 430 431 /* The GPIO should be swapped if the swap register is set and active */ 432 swap_val = REG_RD(pdev, NIG_REG_PORT_SWAP); 433 swap_override = REG_RD(pdev, NIG_REG_STRAP_OVERRIDE); 434 435 436 // define port upon swap 437 gpio_port = (swap_val && swap_override) ^ port; 438 439 // Get the current port number (0 or 1) 440 if (gpio_port > 1) 441 { 442 return LM_STATUS_FAILURE; 443 } 444 445 // Calculate the value with relevent OE set to 1 (for input). 446 // Calulate the mask for the read value. 447 if (gpio_port == 0) 448 { 449 switch (pin_num) 450 { 451 case 0: 452 mask = GRC_MISC_REGISTERS_GPIO_PORT0_VAL0; 453 break; 454 case 1: 455 mask = GRC_MISC_REGISTERS_GPIO_PORT0_VAL1; 456 break; 457 case 2: 458 mask = GRC_MISC_REGISTERS_GPIO_PORT0_VAL2; 459 break; 460 case 3: 461 mask = GRC_MISC_REGISTERS_GPIO_PORT0_VAL3; 462 break; 463 default: 464 break; 465 } 466 } 467 // Calculate the value with relevent OE set to 1 (for input). 468 // Calulate the mask for the read value. 469 if (gpio_port == 1) 470 { 471 switch (pin_num) 472 { 473 case 0: 474 mask = GRC_MISC_REGISTERS_GPIO_PORT1_VAL0; 475 break; 476 case 1: 477 mask = GRC_MISC_REGISTERS_GPIO_PORT1_VAL1; 478 break; 479 case 2: 480 mask = GRC_MISC_REGISTERS_GPIO_PORT1_VAL2; 481 break; 482 case 3: 483 mask = GRC_MISC_REGISTERS_GPIO_PORT1_VAL3; 484 break; 485 default: 486 break; 487 } 488 } 489 490 // Read from MISC block the GPIO register 491 reg_val = REG_RD(pdev, MISC_REG_GPIO); 492 DbgMessage(NULL, INFORM, "lm_gpio_read: MISC_REG_GPIO value 0x%x mask 0x%x\n", reg_val, mask); 493 494 // Get the requested pin value by masking the val with mask 495 if ((reg_val & mask) == mask) 496 { 497 *value_ptr = 1; 498 } 499 else 500 { 501 *value_ptr = 0; 502 } 503 DbgMessage(NULL, INFORM, "lm_gpio_read: pin %d value is %x\n", pin_num, *value_ptr); 504 505 return LM_STATUS_SUCCESS; 506 } 507 508 /* 509 *------------------------------------------------------------------------ 510 * lm_gpio_write - 511 * 512 * Write a value to the requested GPIO pin (with pin_num) 513 * 514 *------------------------------------------------------------------------ 515 */ 516 lm_status_t lm_gpio_write(struct _lm_device_t *pdev, u32_t pin_num, u32_t mode, u8_t port) 517 { 518 u32_t gpio_port = 0; 519 u32_t gpio_shift = 0; 520 u32_t gpio_mask = 0; 521 u32_t gpio_reg = 0; 522 u32_t swap_val = 0; 523 u32_t swap_override = 0; 524 525 if( CHK_NULL(pdev) ) 526 { 527 DbgBreakIf(!pdev); 528 return LM_STATUS_INVALID_PARAMETER ; 529 } 530 if (pin_num > MISC_REGISTERS_GPIO_3) 531 { 532 DbgMessage(pdev, FATAL , "lm_gpio_write: Invalid pin_num GPIO %d\n", pin_num); 533 return LM_STATUS_INVALID_PARAMETER; 534 } 535 536 /* The GPIO should be swapped if the swap register is set and active */ 537 swap_val = REG_RD(pdev, NIG_REG_PORT_SWAP); 538 swap_override = REG_RD(pdev, NIG_REG_STRAP_OVERRIDE); 539 540 // define port upon swap 541 gpio_port = (swap_val && swap_override) ^ port; 542 543 // Get the current port number (0 or 1) 544 if (gpio_port > 1) { 545 return LM_STATUS_FAILURE; 546 } 547 548 gpio_shift = pin_num + 549 (gpio_port ? MISC_REGISTERS_GPIO_PORT_SHIFT : 0); 550 551 gpio_mask = (1 << gpio_shift); 552 553 // lock before read 554 lm_hw_lock(pdev, HW_LOCK_RESOURCE_GPIO, TRUE); 555 556 /* read GPIO and mask except the float bits */ 557 gpio_reg = (REG_RD(pdev, MISC_REG_GPIO) & MISC_REGISTERS_GPIO_FLOAT); 558 559 switch (mode) { 560 case MISC_REGISTERS_GPIO_OUTPUT_LOW: 561 DbgMessage(NULL, WARN, "Set GPIO %d (shift %d) -> output low\n", pin_num, gpio_shift); 562 /* clear FLOAT and set CLR */ 563 gpio_reg &= ~(gpio_mask << MISC_REGISTERS_GPIO_FLOAT_POS); 564 gpio_reg |= (gpio_mask << MISC_REGISTERS_GPIO_CLR_POS); 565 break; 566 567 case MISC_REGISTERS_GPIO_OUTPUT_HIGH: 568 DbgMessage(NULL, WARN, "Set GPIO %d (shift %d) -> output high\n", pin_num, gpio_shift); 569 /* clear FLOAT and set SET */ 570 gpio_reg &= ~(gpio_mask << MISC_REGISTERS_GPIO_FLOAT_POS); 571 gpio_reg |= (gpio_mask << MISC_REGISTERS_GPIO_SET_POS); 572 break; 573 574 case MISC_REGISTERS_GPIO_INPUT_HI_Z: 575 DbgMessage(NULL, WARN, "Set GPIO %d (shift %d) -> input\n", pin_num, gpio_shift); 576 /* set FLOAT */ 577 gpio_reg |= (gpio_mask << MISC_REGISTERS_GPIO_FLOAT_POS); 578 break; 579 580 default: 581 break; 582 } 583 584 REG_WR(pdev, MISC_REG_GPIO, gpio_reg); 585 lm_hw_unlock(pdev, HW_LOCK_RESOURCE_GPIO); 586 587 return LM_STATUS_SUCCESS; 588 589 590 } 591 592 /* 593 *------------------------------------------------------------------------ 594 * lm_gpio_mult_write - 595 * 596 * Write a value to the requested GPIO pins (bits defined) 597 * User is expected to handle any port swapping and know exactly 598 * which pin(s) to drive. 599 * 600 *------------------------------------------------------------------------ 601 */ 602 lm_status_t lm_gpio_mult_write(struct _lm_device_t *pdev, u8_t pins, u32_t mode) 603 { 604 u32_t gpio_reg = 0; 605 lm_status_t rc = LM_STATUS_SUCCESS; 606 607 if( CHK_NULL(pdev) ) 608 { 609 DbgBreakIf(!pdev); 610 return LM_STATUS_INVALID_PARAMETER ; 611 } 612 // lock before read 613 lm_hw_lock(pdev, HW_LOCK_RESOURCE_GPIO, TRUE); 614 615 /* read GPIO and mask except the float bits */ 616 gpio_reg = REG_RD(pdev, MISC_REG_GPIO); 617 gpio_reg &= ~(pins << MISC_REGISTERS_GPIO_FLOAT_POS); 618 gpio_reg &= ~(pins << MISC_REGISTERS_GPIO_CLR_POS); 619 gpio_reg &= ~(pins << MISC_REGISTERS_GPIO_SET_POS); 620 621 switch (mode) { 622 case MISC_REGISTERS_GPIO_OUTPUT_LOW: 623 DbgMessage(NULL, WARN, "Set GPIO 0x%x -> output low\n", pins); 624 /* clear FLOAT and set CLR */ 625 gpio_reg |= (pins << MISC_REGISTERS_GPIO_CLR_POS); 626 break; 627 628 case MISC_REGISTERS_GPIO_OUTPUT_HIGH: 629 DbgMessage(NULL, WARN, "Set GPIO 0x%x -> output high\n", pins); 630 /* clear FLOAT and set SET */ 631 gpio_reg |= (pins << MISC_REGISTERS_GPIO_SET_POS); 632 break; 633 634 case MISC_REGISTERS_GPIO_INPUT_HI_Z: 635 DbgMessage(NULL, WARN, "Set GPIO 0x%x -> input\n", pins); 636 /* set FLOAT */ 637 gpio_reg |= (pins << MISC_REGISTERS_GPIO_FLOAT_POS); 638 break; 639 640 default: 641 DbgMessage(pdev, FATAL , "lm_gpio_mult_write: Invalid GPIO mode %d\n", mode); 642 rc = LM_STATUS_INVALID_PARAMETER; 643 break; 644 } 645 646 if (rc == LM_STATUS_SUCCESS) 647 { 648 REG_WR(pdev, MISC_REG_GPIO, gpio_reg); 649 } 650 651 lm_hw_unlock(pdev, HW_LOCK_RESOURCE_GPIO); 652 653 return rc; 654 } 655 656 /* 657 *------------------------------------------------------------------------ 658 * lm_gpio_int_write - 659 * 660 * Set or clear the requested GPIO pin (with pin_num) 661 * 662 *------------------------------------------------------------------------ 663 */ 664 665 lm_status_t lm_gpio_int_write(struct _lm_device_t *pdev, u32_t pin_num, u32_t mode, u8_t port) 666 { 667 /* The GPIO should be swapped if swap register is set and active */ 668 u32_t gpio_port; 669 u32_t gpio_shift ; 670 u32_t gpio_mask; 671 u32_t gpio_reg; 672 u32_t swap_val = 0; 673 u32_t swap_override = 0; 674 675 swap_val = REG_RD(pdev, NIG_REG_PORT_SWAP); 676 swap_override = REG_RD(pdev, NIG_REG_STRAP_OVERRIDE); 677 gpio_port = (swap_val && swap_override ) ^ port; 678 gpio_shift = pin_num + (gpio_port ? MISC_REGISTERS_GPIO_PORT_SHIFT : 0); 679 gpio_mask = (1 << gpio_shift); 680 681 if (pin_num > MISC_REGISTERS_GPIO_3) 682 { 683 DbgMessage(pdev, FATAL , "lm_gpio_write: Invalid pin_num GPIO %d\n", pin_num); 684 return LM_STATUS_INVALID_PARAMETER; 685 } 686 687 // lock before read 688 lm_hw_lock(pdev, HW_LOCK_RESOURCE_GPIO, TRUE); 689 690 /* read GPIO int */ 691 gpio_reg = REG_RD(pdev, MISC_REG_GPIO_INT); 692 693 switch (mode) 694 { 695 case MISC_REGISTERS_GPIO_INT_OUTPUT_CLR: 696 DbgMessage(pdev, INFORM, "Clear GPIO INT %d (shift %d) -> output low\n", 697 pin_num, gpio_shift); 698 // clear SET and set CLR 699 gpio_reg &= ~(gpio_mask << MISC_REGISTERS_GPIO_INT_SET_POS); 700 gpio_reg |= (gpio_mask << MISC_REGISTERS_GPIO_INT_CLR_POS); 701 break; 702 703 case MISC_REGISTERS_GPIO_INT_OUTPUT_SET: 704 DbgMessage(pdev, INFORM, "Set GPIO INT %d (shift %d) -> output high\n", 705 pin_num, gpio_shift); 706 // clear CLR and set SET 707 gpio_reg &= ~(gpio_mask << MISC_REGISTERS_GPIO_INT_CLR_POS); 708 gpio_reg |= (gpio_mask << MISC_REGISTERS_GPIO_INT_SET_POS); 709 break; 710 711 default: 712 break; 713 } 714 715 REG_WR(pdev, MISC_REG_GPIO_INT, gpio_reg); 716 // unlock after write 717 DbgMessage(pdev, INFORM, "lm_gpio_int_write: pin %d value is %x\n", 718 pin_num, gpio_reg); 719 lm_hw_unlock(pdev, HW_LOCK_RESOURCE_GPIO); 720 721 return 0; 722 } 723 724 /* 725 *------------------------------------------------------------------------ 726 * lm_spio_read - 727 * 728 * Read the value of the requested SPIO pin (with pin_num) 729 * 730 *------------------------------------------------------------------------ 731 */ 732 lm_status_t lm_spio_read(struct _lm_device_t *pdev, u32_t pin_num, u32_t* value_ptr) 733 { 734 u32_t reg_val = 0, mask = 0; 735 736 // Read from MISC block the SPIO register 737 reg_val = REG_RD(pdev, MISC_REG_SPIO); 738 739 DbgMessage(pdev, INFORM, "lm_spio_read: MISC_REG_SPIO value is 0x%x\n", reg_val); 740 741 // Calculate the value with relevent OE set to 1 (for input). 742 // Calulate the mask for the read value. 743 switch (pin_num) { 744 case 0: // SPIO pins 0-2 do not have OE pins 745 mask = MISC_SPIO_EN_VAUX_L; 746 break; 747 case 1: 748 mask = MISC_SPIO_DIS_VAUX_L; 749 break; 750 case 2: 751 mask = MISC_SPIO_SEL_VAUX_L; 752 break; 753 case 3: // SPIO pin 3 is not connected 754 return LM_STATUS_FAILURE; 755 case 4: // SPIO pins 4-7 have OE pins 756 reg_val |= (MISC_SPIO_SPIO4 << MISC_SPIO_FLOAT_POS); 757 mask = MISC_SPIO_SPIO4; 758 break; 759 case 5: 760 reg_val |= (MISC_SPIO_SPIO5 << MISC_SPIO_FLOAT_POS); 761 mask = MISC_SPIO_SPIO5; 762 break; 763 case 6: 764 reg_val |= (MISC_SPIO_UMP_ADDR0 << MISC_SPIO_FLOAT_POS); 765 mask = MISC_SPIO_UMP_ADDR0; 766 break; 767 case 7: 768 reg_val |= (MISC_SPIO_UMP_ADDR1 << MISC_SPIO_FLOAT_POS); 769 mask = MISC_SPIO_UMP_ADDR1; 770 break; 771 default: 772 return LM_STATUS_FAILURE; 773 } 774 775 // Write to SPIO register the value with the relevant OE set to 1 776 REG_WR(pdev, MISC_REG_SPIO, reg_val); 777 DbgMessage(NULL, INFORM, "lm_spio_read: writing MISC_REG_SPIO 0x%x\n", reg_val); 778 779 // Read from MISC block the SPIO register 780 reg_val = REG_RD(pdev, MISC_REG_SPIO); 781 DbgMessage(NULL, INFORM, "lm_spio_read: MISC_REG_SPIO value 0x%x\n", reg_val); 782 783 // Get the requested pin value by masking the val with mask 784 if ((reg_val & mask) == mask) 785 { 786 *value_ptr = 1; 787 } 788 else 789 { 790 *value_ptr = 0; 791 } 792 DbgMessage(NULL, INFORM, "lm_spio_read: pin %d value is 0x%x\n", pin_num, *value_ptr); 793 794 return LM_STATUS_SUCCESS; 795 } 796 797 /* 798 *------------------------------------------------------------------------ 799 * lm_spio_write - 800 * 801 * Write a value to the requested SPIO pin (with pin_num) 802 * 803 *------------------------------------------------------------------------ 804 */ 805 lm_status_t lm_spio_write(struct _lm_device_t *pdev, u32_t pin_num, u32_t value) 806 { 807 u32_t reg_val = 0; 808 lm_status_t lm_status = LM_STATUS_SUCCESS ; 809 810 if CHK_NULL(pdev) 811 { 812 DbgBreakIf(!pdev); 813 return LM_STATUS_INVALID_PARAMETER ; 814 } 815 816 // lock before read 817 lm_hw_lock(pdev, HW_LOCK_RESOURCE_GPIO, TRUE); // The GPIO lock is used for SPIO as well! 818 819 // Read from MISC block the SPIO register 820 reg_val = REG_RD(pdev, MISC_REG_SPIO); 821 DbgMessage(NULL, INFORM, "lm_gpio_write: MISC_REG_SPIO value is 0x%x\n", reg_val); 822 823 // Turn the requested SPIO pin to output by setting its OE bit to 0 and 824 // If value is 1 set the relevant SET bit to 1, otherwise set the CLR bit to 1. 825 if (pin_num >= 8 || pin_num == 3) { 826 // SPIO pin 3 is not connected 827 lm_status = LM_STATUS_FAILURE; 828 } else { 829 u32 pin = 1 << pin_num; 830 // Set pin as OUTPUT 831 reg_val &= ~(pin << MISC_SPIO_FLOAT_POS); 832 // Clear the pins CLR and SET bits 833 reg_val &= ~(pin << MISC_SPIO_SET_POS) & ~(pin << MISC_SPIO_CLR_POS); 834 // If value is 1 set the SET bit of this pin, otherwise set the CLR bit. 835 reg_val |= (value == 1) ? (pin << MISC_SPIO_SET_POS) : (pin << MISC_SPIO_CLR_POS); 836 } 837 838 if( LM_STATUS_SUCCESS == lm_status ) 839 { 840 // Write to SPIO register the value with the relevant OE set to 1 and 841 // If value is 1, set the relevant SET bit to 1, otherwise set the CLR bit to 1. 842 REG_WR(pdev, MISC_REG_SPIO, reg_val); 843 DbgMessage(NULL, INFORM, "lm_spio_write: writing MISC_REG_SPIO 0x%x\n", reg_val); 844 } 845 846 // unlock 847 lm_hw_unlock(pdev, HW_LOCK_RESOURCE_GPIO); 848 849 return lm_status ; 850 } 851 852 853 /* 854 *------------------------------------------------------------------------ 855 * lm_set_led_mode - 856 * 857 * Set the led mode of the requested port 858 * 859 *------------------------------------------------------------------------ 860 */ 861 lm_status_t lm_set_led_mode(struct _lm_device_t *pdev, u32_t port_idx, u32_t mode_idx) 862 { 863 864 DbgBreakIf(!pdev); 865 866 // Write to relevant NIG register LED_MODE (P0 or P1) the mode index (0-15) 867 switch (port_idx) { 868 case 0: 869 REG_WR(pdev, NIG_REG_LED_MODE_P0, mode_idx); 870 break; 871 case 1: 872 REG_WR(pdev, NIG_REG_LED_MODE_P1, mode_idx); 873 break; 874 default: 875 DbgMessage(NULL, FATAL, "lm_set_led_mode() unknown port index %d\n", port_idx); 876 return LM_STATUS_FAILURE; 877 } 878 879 DbgMessage(NULL, INFORM, "lm_set_led_mode() wrote to NIG_REG_LED_MODE (port %d) 0x%x\n", port_idx, mode_idx); 880 return LM_STATUS_SUCCESS; 881 } 882 883 /* 884 *------------------------------------------------------------------------ 885 * lm_get_led_mode - 886 * 887 * Get the led mode of the requested port 888 * 889 *------------------------------------------------------------------------ 890 */ 891 lm_status_t lm_get_led_mode(struct _lm_device_t *pdev, u32_t port_idx, u32_t* mode_idx_ptr) 892 { 893 894 DbgBreakIf(!pdev); 895 896 // Read from the relevant NIG register LED_MODE (P0 or P1) the mode index (0-15) 897 switch (port_idx) { 898 case 0: 899 *mode_idx_ptr = REG_RD(pdev, NIG_REG_LED_MODE_P0); 900 break; 901 case 1: 902 *mode_idx_ptr = REG_RD(pdev, NIG_REG_LED_MODE_P1); 903 break; 904 default: 905 DbgMessage(NULL, FATAL, "lm_get_led_mode() unknown port index %d\n", port_idx); 906 return LM_STATUS_FAILURE; 907 } 908 909 DbgMessage(NULL, INFORM, "lm_get_led_mode() read from NIG_REG_LED_MODE (port %d) 0x%x\n", port_idx, *mode_idx_ptr); 910 911 return LM_STATUS_SUCCESS; 912 } 913 914 /* 915 *------------------------------------------------------------------------ 916 * lm_override_led_value - 917 * 918 * Override the led value of the requsted led 919 * 920 *------------------------------------------------------------------------ 921 */ 922 lm_status_t lm_override_led_value(struct _lm_device_t *pdev, u32_t port_idx, u32_t led_idx, u32_t value) 923 { 924 u32_t reg_val = 0; 925 926 // If port 0 then use EMAC0, else use EMAC1 927 u32_t emac_base = (port_idx) ? GRCBASE_EMAC1 : GRCBASE_EMAC0; 928 929 DbgBreakIf(!pdev); 930 931 DbgMessage(NULL, INFORM, "lm_override_led_value() port %d led_idx %d value %d\n", port_idx, led_idx, value); 932 933 switch (led_idx) { 934 case 0: //10MB led 935 // Read the current value of the LED register in the EMAC block 936 reg_val = REG_RD(pdev, emac_base + EMAC_REG_EMAC_LED); 937 // Set the OVERRIDE bit to 1 938 reg_val |= EMAC_LED_OVERRIDE; 939 // If value is 1, set the 10M_OVERRIDE bit, otherwise reset it. 940 reg_val = (value==1) ? (reg_val | EMAC_LED_10MB_OVERRIDE) : (reg_val & ~EMAC_LED_10MB_OVERRIDE); 941 REG_WR(pdev, emac_base+ EMAC_REG_EMAC_LED, reg_val); 942 break; 943 case 1: //100MB led 944 // Read the current value of the LED register in the EMAC block 945 reg_val = REG_RD(pdev, emac_base + EMAC_REG_EMAC_LED); 946 // Set the OVERRIDE bit to 1 947 reg_val |= EMAC_LED_OVERRIDE; 948 // If value is 1, set the 100M_OVERRIDE bit, otherwise reset it. 949 reg_val = (value==1) ? (reg_val | EMAC_LED_100MB_OVERRIDE) : (reg_val & ~EMAC_LED_100MB_OVERRIDE); 950 REG_WR(pdev, emac_base+ EMAC_REG_EMAC_LED, reg_val); 951 break; 952 case 2: //1000MB led 953 // Read the current value of the LED register in the EMAC block 954 reg_val = REG_RD(pdev, emac_base + EMAC_REG_EMAC_LED); 955 // Set the OVERRIDE bit to 1 956 reg_val |= EMAC_LED_OVERRIDE; 957 // If value is 1, set the 1000M_OVERRIDE bit, otherwise reset it. 958 reg_val = (value==1) ? (reg_val | EMAC_LED_1000MB_OVERRIDE) : (reg_val & ~EMAC_LED_1000MB_OVERRIDE); 959 REG_WR(pdev, emac_base+ EMAC_REG_EMAC_LED, reg_val); 960 break; 961 case 3: //2500MB led 962 // Read the current value of the LED register in the EMAC block 963 reg_val = REG_RD(pdev, emac_base + EMAC_REG_EMAC_LED); 964 // Set the OVERRIDE bit to 1 965 reg_val |= EMAC_LED_OVERRIDE; 966 // If value is 1, set the 2500M_OVERRIDE bit, otherwise reset it. 967 reg_val = (value==1) ? (reg_val | EMAC_LED_2500MB_OVERRIDE) : (reg_val & ~EMAC_LED_2500MB_OVERRIDE); 968 REG_WR(pdev, emac_base+ EMAC_REG_EMAC_LED, reg_val); 969 break; 970 case 4: //10G led 971 if (port_idx == 0) { 972 REG_WR(pdev, NIG_REG_LED_10G_P0, value); 973 } else { 974 REG_WR(pdev, NIG_REG_LED_10G_P1, value); 975 } 976 break; 977 case 5: //TRAFFIC led 978 979 // Find if the traffic control is via BMAC or EMAC 980 if (port_idx == 0) { 981 reg_val = REG_RD(pdev, NIG_REG_NIG_EMAC0_EN); 982 } else { 983 reg_val = REG_RD(pdev, NIG_REG_NIG_EMAC1_EN); 984 } 985 986 // Override the traffic led in the EMAC: 987 if (reg_val == 1) { 988 // Read the current value of the LED register in the EMAC block 989 reg_val = REG_RD(pdev, emac_base + EMAC_REG_EMAC_LED); 990 // Set the TRAFFIC_OVERRIDE bit to 1 991 reg_val |= EMAC_LED_OVERRIDE; 992 // If value is 1, set the TRAFFIC bit, otherwise reset it. 993 reg_val = (value==1) ? (reg_val | EMAC_LED_TRAFFIC) : (reg_val & ~EMAC_LED_TRAFFIC); 994 REG_WR(pdev, emac_base+ EMAC_REG_EMAC_LED, reg_val); 995 } else { // Override the traffic led in the BMAC: 996 if (port_idx == 0) { 997 REG_WR(pdev, NIG_REG_LED_CONTROL_OVERRIDE_TRAFFIC_P0, 1); 998 REG_WR(pdev, NIG_REG_LED_CONTROL_TRAFFIC_P0, value); 999 } else { 1000 REG_WR(pdev, NIG_REG_LED_CONTROL_OVERRIDE_TRAFFIC_P1, 1); 1001 REG_WR(pdev, NIG_REG_LED_CONTROL_TRAFFIC_P1, value); 1002 } 1003 } 1004 break; 1005 default: 1006 DbgMessage(NULL, FATAL, "lm_override_led_value() unknown led index %d (should be 0-5)\n", led_idx); 1007 return LM_STATUS_FAILURE; 1008 } 1009 1010 return LM_STATUS_SUCCESS; 1011 } 1012 1013 /* 1014 *------------------------------------------------------------------------ 1015 * lm_blink_traffic_led - 1016 * 1017 * Blink the traffic led with the requsted rate 1018 * 1019 *------------------------------------------------------------------------ 1020 */ 1021 lm_status_t lm_blink_traffic_led(struct _lm_device_t *pdev, u32_t port_idx, u32_t rate) 1022 { 1023 u32_t reg_val = 0; 1024 // If port 0 then use EMAC0, else use EMAC1 1025 u32_t emac_base = (port_idx) ? GRCBASE_EMAC1 : GRCBASE_EMAC0; 1026 1027 DbgBreakIf(!pdev); 1028 1029 // Find if the traffic control is via BMAC or EMAC 1030 if (port_idx == 0) { 1031 reg_val = REG_RD(pdev, NIG_REG_NIG_EMAC0_EN); 1032 } else { 1033 reg_val = REG_RD(pdev, NIG_REG_NIG_EMAC1_EN); 1034 } 1035 1036 // Blink the traffic led using EMAC control: 1037 if (reg_val == 1) { 1038 // Read the current value of the LED register in the EMAC block 1039 reg_val = REG_RD(pdev, emac_base + EMAC_REG_EMAC_LED); 1040 1041 // Set the TRAFFIC_OVERRIDE, TRAFFIC and BLNK_TRAFFIC to 1 1042 reg_val |= EMAC_LED_OVERRIDE; 1043 reg_val |= EMAC_LED_TRAFFIC; 1044 reg_val |= EMAC_LED_BLNK_TRAFFIC; 1045 1046 // If rate field was entered then set the BLNK_RATE_ENA bit and the BLNK_RATE field, 1047 // Otherwise the blink rate will be about 16Hz 1048 if (rate != 0) { 1049 reg_val |= EMAC_LED_BLNK_RATE_ENA; 1050 reg_val |= (rate << EMAC_LED_BLNK_RATE_BITSHIFT); 1051 } 1052 REG_WR(pdev, emac_base+ EMAC_REG_EMAC_LED, reg_val); 1053 DbgMessage(NULL, INFORM, "lm_blink_traffic_led() port %d write to EMAC_REG_EMAC_LED the value 0x%x\n", port_idx, reg_val); 1054 1055 } else { // Blink the traffic led in the BMAC: 1056 // Set the CONTROL_OVERRIDE_TRAFFIC and the CONTROL_BLINK_TRAFFIC to 1. 1057 if (port_idx == 0) { 1058 REG_WR(pdev, NIG_REG_LED_CONTROL_OVERRIDE_TRAFFIC_P0, 1); 1059 REG_WR(pdev, NIG_REG_LED_CONTROL_TRAFFIC_P0, 1); 1060 REG_WR(pdev, NIG_REG_LED_CONTROL_BLINK_TRAFFIC_P0, 1); 1061 DbgMessage(NULL, INFORM, "lm_blink_traffic_led() set BLINK_TRAFFIC_P0 to 1\n"); 1062 // If the rate field was entered, update the BLINK_RATE register accordingly 1063 if (rate != 0) { 1064 REG_WR(pdev, NIG_REG_LED_CONTROL_BLINK_RATE_ENA_P0, 1); 1065 REG_WR(pdev, NIG_REG_LED_CONTROL_BLINK_RATE_P0, rate); 1066 DbgMessage(NULL, INFORM, "lm_blink_traffic_led() port %d write to NIG_REG_LED_CONTROL_BLINK_RATE_P0 %x\n", port_idx, rate); 1067 } 1068 } else { 1069 REG_WR(pdev, NIG_REG_LED_CONTROL_OVERRIDE_TRAFFIC_P1, 1); 1070 REG_WR(pdev, NIG_REG_LED_CONTROL_TRAFFIC_P1, 1); 1071 REG_WR(pdev, NIG_REG_LED_CONTROL_BLINK_TRAFFIC_P1, 1); 1072 DbgMessage(NULL, INFORM, "lm_blink_traffic_led() set BLINK_TRAFFIC_P1 to 1\n"); 1073 // If the rate field was entered, update the BLINK_RATE register accordingly 1074 if (rate != 0) { 1075 REG_WR(pdev, NIG_REG_LED_CONTROL_BLINK_RATE_ENA_P1, 1); 1076 REG_WR(pdev, NIG_REG_LED_CONTROL_BLINK_RATE_P1, rate); 1077 DbgMessage(NULL, INFORM, "lm_blink_traffic_led() port %d write to NIG_REG_LED_CONTROL_BLINK_RATE_P1 0x%x\n", port_idx, rate); 1078 } 1079 } 1080 } 1081 return LM_STATUS_SUCCESS; 1082 } 1083 1084 /* 1085 *------------------------------------------------------------------------ 1086 * lm_get_led_status - 1087 * 1088 * Get the led status of the requsted led, on the requested port 1089 * 1090 *------------------------------------------------------------------------ 1091 */ 1092 lm_status_t lm_get_led_status(struct _lm_device_t *pdev, u32_t port_idx, u32_t led_idx, u32_t* value_ptr) 1093 { 1094 u32_t reg_val = 0; 1095 1096 // If port 0 then use EMAC0, else use EMAC1 1097 u32_t emac_base = (port_idx) ? GRCBASE_EMAC1 : GRCBASE_EMAC0; 1098 1099 DbgBreakIf(!pdev); 1100 1101 switch (led_idx) { 1102 case 0: //10MB LED 1103 // Read the current value of the LED register in the EMAC block 1104 reg_val = REG_RD(pdev, emac_base + EMAC_REG_EMAC_LED); 1105 // Check the 10MB bit status 1106 *value_ptr = ((reg_val & EMAC_LED_10MB) == EMAC_LED_10MB) ? 1 : 0; 1107 break; 1108 case 1: //100MB LED 1109 // Read the current value of the LED register in the EMAC block 1110 reg_val = REG_RD(pdev, emac_base + EMAC_REG_EMAC_LED); 1111 // Check the 100MB bit status 1112 *value_ptr = ((reg_val & EMAC_LED_100MB) == EMAC_LED_100MB) ? 1 : 0; 1113 break; 1114 case 2: //1000MB LED 1115 // Read the current value of the LED register in the EMAC block 1116 reg_val = REG_RD(pdev, emac_base + EMAC_REG_EMAC_LED); 1117 // Check the 1000MB bit status 1118 *value_ptr = ((reg_val & EMAC_LED_1000MB) == EMAC_LED_1000MB) ? 1 : 0; 1119 break; 1120 case 3: //2500MB LED 1121 // Read the current value of the LED register in the EMAC block 1122 reg_val = REG_RD(pdev, emac_base + EMAC_REG_EMAC_LED); 1123 // Check the 2500MB bit status 1124 *value_ptr = ((reg_val & EMAC_LED_2500MB) == EMAC_LED_2500MB) ? 1 : 0; 1125 break; 1126 case 4: //10G LED 1127 if (port_idx == 0) { 1128 *value_ptr = REG_RD(pdev, NIG_REG_LED_10G_P0); 1129 } else { 1130 *value_ptr = REG_RD(pdev, NIG_REG_LED_10G_P1); 1131 } 1132 break; 1133 case 5: //TRAFFIC LED 1134 // Read the traffic led from the EMAC block 1135 reg_val = REG_RD(pdev, emac_base + EMAC_REG_EMAC_LED); 1136 // Check the TRAFFIC_STAT bit status 1137 *value_ptr = ((reg_val & EMAC_LED_TRAFFIC_STAT) == EMAC_LED_TRAFFIC_STAT) ? 1 : 0; 1138 1139 // Read the traffic led from the BMAC block 1140 if (port_idx == 0) { 1141 *value_ptr = REG_RD(pdev, NIG_REG_LED_STATUS_ACTIVE_P0); 1142 } else { 1143 *value_ptr = REG_RD(pdev, NIG_REG_LED_STATUS_ACTIVE_P1); 1144 } 1145 break; 1146 default: 1147 DbgMessage(NULL, FATAL, "lm_get_led_status() unknown led index %d (should be 0-5)\n", led_idx); 1148 return LM_STATUS_FAILURE; 1149 } 1150 1151 DbgMessage(NULL, INFORM, "lm_get_led_status() port %d led_idx %d value %d\n", port_idx, led_idx, *value_ptr); 1152 1153 return LM_STATUS_SUCCESS; 1154 1155 } 1156 1157 /* 1158 *------------------------------------------------------------------------ 1159 * lm_reset_led - 1160 * 1161 * Sets the LEDs to operational mode after establishing link 1162 * 1163 *------------------------------------------------------------------------ 1164 */ 1165 void 1166 lm_reset_led(struct _lm_device_t *pdev) 1167 { 1168 //u32_t val; 1169 u8_t port = 0; 1170 1171 if (CHK_NULL(pdev)){ 1172 DbgBreakIf(!pdev); 1173 return; 1174 } 1175 port = PORT_ID(pdev); 1176 1177 REG_WR(pdev, NIG_REG_LED_10G_P0 + port*4, 0); 1178 REG_WR(pdev, NIG_REG_LED_MODE_P0 + port*4,SHARED_HW_CFG_LED_MAC1); 1179 } 1180 1181 static u8_t lm_is_57710A0_dbg_intr( struct _lm_device_t * pdev ) 1182 { 1183 u32_t val = 0; 1184 1185 /* if during MSI/MSI-X mode then take no action (different problem) */ 1186 if(pdev->params.interrupt_mode != LM_INT_MODE_INTA) 1187 { 1188 DbgMessage(pdev, WARN, "MSI/MSI-X enabled - debugging INTA/B failed\n"); 1189 return 0; 1190 } 1191 1192 /* read status from PCIE core */ 1193 val = REG_RD(pdev, 0x2004); 1194 1195 /* if interrupt line value from PCIE core is not asserted then take no action (different problem) */ 1196 #define PCIE_CORE_INT_PENDING_BIT 0X00080000 /* when this bit is set, interrupt is asserted (pending) */ 1197 if(!GET_FLAGS(val, PCIE_CORE_INT_PENDING_BIT)) 1198 { 1199 DbgMessage(pdev, WARN, "PCIE core int line not asserted - debugging INTA/B failed\n"); 1200 return 0; 1201 } 1202 1203 /* if interrupt line from PCIE core is not enabled then take no action (different problem) */ 1204 #define PCIE_CORE_INT_DISABLE_BIT 0X00000400 /* when this bit is set, interrupt is disabled */ 1205 if(GET_FLAGS(val, PCIE_CORE_INT_DISABLE_BIT)) 1206 { 1207 DbgMessage(pdev, WARN, "PCIE core int line not enabled - debugging INTA/B failed\n"); 1208 return 0; 1209 } 1210 1211 /* read interrupt mask from IGU */ 1212 val = REG_RD(pdev, HC_REG_INT_MASK + 4*PORT_ID(pdev) ); 1213 1214 /* if not 1FFFF then write warning to log (suspected as different problem) and continue to following step */ 1215 if(val != 0x0001ffff) 1216 { 1217 DbgMessage(pdev, WARN, "IGU int mask != 0x1ffff - might not be related to debugging INTA/B issue\n"); 1218 } 1219 1220 /* verify that int_line_en_0/1 is 1. If bit is clear then no action write warning to log and return. */ 1221 // We skip this check. 1222 1223 return 1; 1224 } 1225 1226 /** lm_57710A0_dbg_intr 1227 * 1228 * Description: 1229 * 1. some sanity checks that the case we have is indeed the 1230 * interrupt debugging mode. 1231 * 2. Apply special handling, that is to disable and enable 1232 * INTA/B in IGU 1233 */ 1234 void lm_57710A0_dbg_intr( struct _lm_device_t * pdev ) 1235 { 1236 if(IS_CHIP_REV_A0(pdev) && lm_is_57710A0_dbg_intr(pdev)) 1237 { 1238 lm_disable_int(pdev); 1239 lm_enable_int(pdev); 1240 } 1241 } 1242 1243 /******************************************************************************* 1244 * Description: turn led on/off/operational mode 1245 * Must be called under PHY_LOCK 1246 * Return: 1247 ******************************************************************************/ 1248 lm_status_t 1249 lm_set_led_wrapper(struct _lm_device_t* pdev, 1250 const u8_t led_mode ) 1251 { 1252 u8_t elink_res = ELINK_STATUS_OK; 1253 lm_status_t lm_status = LM_STATUS_SUCCESS; 1254 1255 PHY_HW_LOCK(pdev); 1256 elink_res = elink_set_led( &pdev->params.link, &pdev->vars.link, led_mode, pdev->vars.link.line_speed ); 1257 PHY_HW_UNLOCK(pdev); 1258 1259 switch(elink_res) 1260 { 1261 case ELINK_STATUS_OK: 1262 lm_status = LM_STATUS_SUCCESS; 1263 break; 1264 1265 case ELINK_STATUS_ERROR: 1266 default: 1267 lm_status = LM_STATUS_FAILURE; 1268 break; 1269 }// switch elink_res 1270 1271 return lm_status; 1272 } /* lm_set_led */ 1273 1274 /******************************************************************************* 1275 * Description: Reads the parametrs using elink interface 1276 * Must be called under PHY_LOCK 1277 * Return: 1278 ******************************************************************************/ 1279 lm_status_t 1280 lm_get_transceiver_data(struct _lm_device_t* pdev, 1281 b10_transceiver_data_t* b10_transceiver_data ) 1282 { 1283 u16_t eeprom_data[][2] = { { ELINK_SFP_EEPROM_VENDOR_NAME_ADDR, ELINK_SFP_EEPROM_VENDOR_NAME_SIZE}, 1284 { ELINK_SFP_EEPROM_PART_NO_ADDR, ELINK_SFP_EEPROM_PART_NO_SIZE}, 1285 { ELINK_SFP_EEPROM_SERIAL_ADDR, ELINK_SFP_EEPROM_SERIAL_SIZE}, 1286 { ELINK_SFP_EEPROM_REVISION_ADDR, ELINK_SFP_EEPROM_REVISION_SIZE}, 1287 { ELINK_SFP_EEPROM_DATE_ADDR, ELINK_SFP_EEPROM_DATE_SIZE} } ; 1288 1289 u8_t vendor_name [ELINK_SFP_EEPROM_VENDOR_NAME_SIZE] = {0}; 1290 u8_t model_num [ELINK_SFP_EEPROM_PART_NO_SIZE] = {0}; 1291 u8_t serial_num [ELINK_SFP_EEPROM_SERIAL_SIZE] = {0}; 1292 u8_t revision_num [ELINK_SFP_EEPROM_REVISION_SIZE] = {0}; 1293 u8_t mfg_date [ELINK_SFP_EEPROM_DATE_SIZE] = {0}; 1294 u8_t* ptr_arr[ARRSIZE(eeprom_data)] = {0}; // for convinence of coding 1295 u8_t idx = 0; 1296 u8_t elink_res = ELINK_STATUS_ERROR; 1297 u8_t ext_phy_type = 0; 1298 lm_status_t lm_status = LM_STATUS_SUCCESS; 1299 1300 // we use local variables (vendor_name, model_num etc...) to protect flows in IA64 1301 // that upper layer might send us non-aligned to u16_t pointer, in this case a BSOD might occur. 1302 // using local variables and than memcpy prevent such situation. 1303 1304 if CHK_NULL( b10_transceiver_data ) 1305 { 1306 return LM_STATUS_INVALID_PARAMETER; 1307 } 1308 1309 ASSERT_STATIC( sizeof(b10_transceiver_data->vendor_name) == sizeof(vendor_name) ) ; 1310 ASSERT_STATIC( sizeof(b10_transceiver_data->model_num) == sizeof(model_num) ) ; 1311 ASSERT_STATIC( sizeof(b10_transceiver_data->serial_num) == sizeof(serial_num) ) ; 1312 ASSERT_STATIC( sizeof(b10_transceiver_data->revision_num) == sizeof(revision_num) ) ; 1313 ASSERT_STATIC( sizeof(b10_transceiver_data->mfg_date) == sizeof(mfg_date) ) ; 1314 1315 mm_mem_zero( b10_transceiver_data, sizeof( b10_transceiver_data_t ) ) ; 1316 1317 ptr_arr[0] = &vendor_name[0]; 1318 ptr_arr[1] = &model_num[0]; 1319 ptr_arr[2] = &serial_num[0]; 1320 ptr_arr[3] = &revision_num[0]; 1321 ptr_arr[4] = &mfg_date[0]; 1322 1323 if( pdev->params.link.num_phys > ELINK_MAX_PHYS ) 1324 { 1325 DbgBreakIf(1); 1326 return LM_STATUS_FAILURE; 1327 } 1328 1329 // query from elink all ext_phy types (currently 1 and 2) 1330 for( ext_phy_type = ELINK_EXT_PHY1; ext_phy_type < pdev->params.link.num_phys; ext_phy_type++ ) 1331 { 1332 if( ELINK_ETH_PHY_SFPP_10G_FIBER == pdev->params.link.phy[ext_phy_type].media_type || 1333 ELINK_ETH_PHY_SFP_1G_FIBER == pdev->params.link.phy[ext_phy_type].media_type || 1334 ELINK_ETH_PHY_DA_TWINAX == pdev->params.link.phy[ext_phy_type].media_type) 1335 { 1336 // only in case not SFP+ - the elink query is supported 1337 for( idx = 0; idx < ARRSIZE(eeprom_data) ; idx++ ) 1338 { 1339 PHY_HW_LOCK(pdev); 1340 elink_res = elink_read_sfp_module_eeprom( &pdev->params.link.phy[ext_phy_type], // ELINK_INT_PHY, ELINK_EXT_PHY1, ELINK_EXT_PHY2 1341 &pdev->params.link, 1342 ELINK_I2C_DEV_ADDR_A0, 1343 eeprom_data[idx][0], 1344 (u8_t)eeprom_data[idx][1], 1345 ptr_arr[idx] ) ; 1346 PHY_HW_UNLOCK(pdev); 1347 if( ELINK_STATUS_OK != elink_res ) 1348 { 1349 // We assume that if one of the queries failed - there is an error so we break this loop 1350 break; 1351 } 1352 1353 } // for "eeprom_data" size 1354 1355 // only one sfp+ module is expected on board so we exit the ext_phy_type loop 1356 break; 1357 1358 } // ELINK_ETH_PHY_SFP_FIBER == media_type 1359 1360 } // for "ext_phy_type" 1361 1362 switch(elink_res) 1363 { 1364 case ELINK_STATUS_OK: 1365 { 1366 b10_transceiver_data->ver_num = TRANSCEIVER_DATA_VER_NUM; 1367 1368 mm_memcpy( b10_transceiver_data->vendor_name, &vendor_name[0], sizeof(vendor_name) ); 1369 mm_memcpy( b10_transceiver_data->model_num, &model_num[0], sizeof(model_num) ); 1370 mm_memcpy( b10_transceiver_data->serial_num, &serial_num[0], sizeof(serial_num) ); 1371 mm_memcpy( b10_transceiver_data->revision_num, &revision_num[0], sizeof(revision_num) ); 1372 mm_memcpy( b10_transceiver_data->mfg_date, &mfg_date[0], sizeof(mfg_date) ); 1373 } 1374 lm_status = LM_STATUS_SUCCESS; 1375 break; 1376 1377 case ELINK_STATUS_TIMEOUT: 1378 lm_status = LM_STATUS_TIMEOUT; 1379 break; 1380 1381 case ELINK_STATUS_ERROR: 1382 default: 1383 lm_status = LM_STATUS_FAILURE; 1384 break; 1385 }// switch elink_res 1386 1387 return lm_status; 1388 1389 } /* lm_get_transceiver_data */ 1390 1391 lm_status_t lm_set_mac_in_nig(lm_device_t * pdev, u8_t * mac_addr, lm_cli_idx_t lm_cli_idx, u8_t offset) 1392 { 1393 u32_t reg_offset = 0; 1394 u32_t wb_data[2] = {0}; 1395 u8_t enable_mac = 0; 1396 1397 #define MAX_OFFSET_IN_MEM_1 8 1398 1399 if (lm_cli_idx == LM_CLI_IDX_ISCSI) 1400 { 1401 offset = ECORE_LLH_CAM_ISCSI_ETH_LINE; 1402 } 1403 else if (offset == ECORE_LLH_CAM_ISCSI_ETH_LINE) 1404 { 1405 offset = MAX_MAC_OFFSET_IN_NIG; /* Invalidate offset if not iscsi and its in iscsi place */ 1406 } 1407 1408 /* We set the macs in the nig llh only for E2 SI/NIV mode and for NDIS only (first 16 entries) */ 1409 if (CHIP_IS_E1x(pdev) || !IS_MULTI_VNIC(pdev) || IS_MF_SD_MODE(pdev) || offset >= MAX_MAC_OFFSET_IN_NIG) 1410 { 1411 return LM_STATUS_SUCCESS; 1412 } 1413 1414 /* in switch-independt mode we need to configure the NIG LLH with the appropriate mac addresses, we use the 1415 * cam mapping 1--1 for all indices smaller than 16 */ 1416 if (mac_addr) 1417 { 1418 DbgMessage(pdev, WARN, "Setting mac in nig to offset: %d mac_addr[%02x]:[%02x]:[%02x]:[%02x]:[%02x]:[%02x]\n", offset, 1419 mac_addr[0], mac_addr[1], mac_addr[2], mac_addr[3], mac_addr[4], mac_addr[5]); 1420 DbgMessage(pdev, WARN, "[%x]:[%x]\n", mac_addr[6], mac_addr[7]); 1421 1422 if (offset < MAX_OFFSET_IN_MEM_1) 1423 { 1424 reg_offset = (PORT_ID(pdev)? NIG_REG_LLH1_FUNC_MEM: NIG_REG_LLH0_FUNC_MEM) + 8*offset; 1425 } 1426 else 1427 { 1428 reg_offset = (PORT_ID(pdev)? NIG_REG_P1_LLH_FUNC_MEM2: NIG_REG_P0_LLH_FUNC_MEM2) + 8*(offset - MAX_OFFSET_IN_MEM_1); 1429 } 1430 1431 wb_data[0] = ((mac_addr[2] << 24) | (mac_addr[3] << 16) | (mac_addr[4] << 8) | mac_addr[5]); 1432 wb_data[1] = ((mac_addr[0] << 8) | mac_addr[1]); 1433 1434 REG_WR_DMAE_LEN(pdev, reg_offset, wb_data, ARRSIZE(wb_data)); 1435 1436 enable_mac = 1; 1437 } 1438 1439 DbgMessage(pdev, WARN, "Enable_mac: %d\n", enable_mac); 1440 1441 if (offset < MAX_OFFSET_IN_MEM_1) 1442 { 1443 reg_offset = (PORT_ID(pdev)? NIG_REG_LLH1_FUNC_MEM_ENABLE : NIG_REG_LLH0_FUNC_MEM_ENABLE) + 4*offset; 1444 } 1445 else 1446 { 1447 reg_offset = (PORT_ID(pdev)? NIG_REG_P1_LLH_FUNC_MEM2_ENABLE : NIG_REG_P0_LLH_FUNC_MEM2_ENABLE) + 4*(offset - MAX_OFFSET_IN_MEM_1); 1448 } 1449 REG_WR(pdev, reg_offset, enable_mac); 1450 1451 return LM_STATUS_SUCCESS; 1452 } 1453 1454 /** 1455 * Table to lookup appropriate lock register for function. 1456 * 1457 * Indexed with func ID (0-7). 1458 * 1459 * Note registers are *not* consecutive, thus table. 1460 */ 1461 1462 static const u32_t lm_hw_lock_table[8] = { 1463 MISC_REG_DRIVER_CONTROL_1, /* 0 */ 1464 MISC_REG_DRIVER_CONTROL_2, /* 1 */ 1465 MISC_REG_DRIVER_CONTROL_3, /* 2 */ 1466 MISC_REG_DRIVER_CONTROL_4, /* 3 */ 1467 MISC_REG_DRIVER_CONTROL_5, /* 4 */ 1468 MISC_REG_DRIVER_CONTROL_6, /* 5 */ 1469 MISC_REG_DRIVER_CONTROL_7, /* 6 */ 1470 MISC_REG_DRIVER_CONTROL_8, /* 7 */ 1471 }; 1472 1473 /******************************************************************************* 1474 * Description: 1475 * Acquiring the HW lock for a specific resource. 1476 * The assumption is that only 1 bit is set in the resource parameter 1477 * There is a HW attention in case the same function attempts to 1478 * acquire the same lock more than once 1479 * 1480 * Params: 1481 * resource: the HW LOCK Register name 1482 * b_block: Try to get lock until succesful, or backout immediately on failure. 1483 * Return: 1484 * Success - got the lock 1485 * Fail - Invalid parameter or could not obtain the lock for our 1 sec in block mode 1486 * or couldn't obtain lock one-shot in non block mode 1487 ******************************************************************************/ 1488 lm_status_t lm_hw_lock( lm_device_t* pdev, 1489 const u32_t resource, 1490 const u8_t b_block) 1491 { 1492 u32_t cnt = 0; 1493 u32_t lock_status = 0; 1494 u32_t const resource_bit = (1 << resource); 1495 u8_t const func = FUNC_ID(pdev); 1496 u32_t hw_lock_cntr_reg = 0; 1497 1498 // Validating the resource in within range 1499 if (resource > HW_LOCK_MAX_RESOURCE_VALUE) 1500 { 1501 DbgMessage(pdev, FATAL, "lm_hw_lock: LM_STATUS_INVALID_PARAMETER resource=0x%x\n", resource); 1502 DbgBreakMsg("lm_hw_lock: LM_STATUS_INVALID_PARAMETER\n"); 1503 return LM_STATUS_INVALID_PARAMETER; 1504 } 1505 1506 DbgBreakIf(func >= ARRSIZE(lm_hw_lock_table)); 1507 hw_lock_cntr_reg = lm_hw_lock_table[func]; 1508 1509 // Validating that the resource is not already taken 1510 lock_status = REG_RD(pdev, hw_lock_cntr_reg); 1511 if (lock_status & resource_bit) 1512 { 1513 DbgMessage(pdev, FATAL , "lm_hw_lock: LM_STATUS_EXISTING_OBJECT lock_status=0x%x resource_bit=0x%x\n", lock_status, resource_bit); 1514 DbgBreakMsg("lm_hw_lock: LM_STATUS_EXISTING_OBJECT\n"); 1515 return LM_STATUS_EXISTING_OBJECT; 1516 } 1517 // Try for 16 second every 50us 1518 for (cnt = 0; cnt < 320000; cnt++) 1519 { 1520 // Try to acquire the lock 1521 REG_WR(pdev, hw_lock_cntr_reg + 4, resource_bit); 1522 lock_status= REG_RD(pdev, hw_lock_cntr_reg); 1523 if (lock_status & resource_bit) 1524 { 1525 return LM_STATUS_SUCCESS; 1526 } 1527 if (!b_block) 1528 { 1529 return LM_STATUS_FAILURE; 1530 } 1531 mm_wait(pdev, 50); 1532 } 1533 DbgMessage(pdev, FATAL , "lm_hw_lock: LM_STATUS_TIMEOUT\n" ); 1534 DbgBreakMsg("lm_hw_lock: FAILED LM_STATUS_TIMEOUT\n"); 1535 return LM_STATUS_TIMEOUT; 1536 } 1537 /******************************************************************************* 1538 * Description: 1539 * Releasing the HW lock for a specific resource. 1540 * There is a HW attention in case the a function attempts to release 1541 * a lock that it did not acquire (if b_verify_locked is TRUE, default) 1542 * Return: 1543 * Success - if the parameter is valid, the assumption is that it 1544 * will succeed 1545 * Fail - Invalid parameter 1546 ******************************************************************************/ 1547 lm_status_t lm_hw_unlock_ex(lm_device_t* pdev, 1548 const u32_t resource, 1549 const u8_t b_verify_locked ) 1550 { 1551 u32_t lock_status = 0; 1552 u32_t const resource_bit = (1 << resource); 1553 u8_t const func = FUNC_ID(pdev); 1554 u32_t hw_lock_cntr_reg = 0; 1555 1556 // Validating the resource in within range 1557 if (resource > HW_LOCK_MAX_RESOURCE_VALUE) 1558 { 1559 DbgMessage(pdev, FATAL, "lm_hw_unlock: LM_STATUS_INVALID_PARAMETER resource=0x%x\n", resource); 1560 DbgBreakMsg("lm_hw_unlock: LM_STATUS_INVALID_PARAMETER\n"); 1561 return LM_STATUS_INVALID_PARAMETER; 1562 } 1563 1564 DbgBreakIf(func >= ARRSIZE(lm_hw_lock_table)); 1565 hw_lock_cntr_reg = lm_hw_lock_table[func]; 1566 1567 // Validating that the resource is currently taken 1568 lock_status = REG_RD(pdev, hw_lock_cntr_reg); 1569 if (!(lock_status & resource_bit)) 1570 { 1571 // This comment is explicitly outside the IF since we still want to be aware it happened. 1572 DbgMessage(pdev, FATAL, "lm_hw_unlock: LM_STATUS_OBJECT_NOT_FOUND lock_status=0x%x resource_bit=0x%x\n", lock_status, resource_bit); 1573 1574 if( b_verify_locked ) 1575 { 1576 DbgBreakMsg("lm_hw_unlock: LM_STATUS_OBJECT_NOT_FOUND\n"); 1577 return LM_STATUS_OBJECT_NOT_FOUND; 1578 } 1579 } 1580 REG_WR(pdev, hw_lock_cntr_reg, resource_bit); 1581 1582 return LM_STATUS_SUCCESS; 1583 } 1584 1585 /******************************************************************************* 1586 * Description: 1587 * Releasing the HW lock for a specific resource. 1588 * There is a HW attention in case the a function attempts to release 1589 * a lock that it did not acquire 1590 THIS function is a wrapper function now for lm_hw_unlock_ex. 1591 * Return: 1592 * Success - if the parameter is valid, the assumption is that it 1593 * will succeed 1594 * Fail - Invalid parameter 1595 ******************************************************************************/ 1596 lm_status_t lm_hw_unlock(lm_device_t* pdev, 1597 const u32_t resource) 1598 { 1599 return lm_hw_unlock_ex( pdev, resource, TRUE); 1600 } 1601 1602 /** 1603 * @Desription 1604 * This function is used to recover from a state where the 1605 * locks stayed in "taken" state during a reboot. We want 1606 * to clear all the locks before proceeding. 1607 * 1608 * @param pdev 1609 */ 1610 void lm_hw_clear_all_locks(lm_device_t *pdev) 1611 { 1612 u32_t lock_status = 0; 1613 u32_t hw_lock_cntr_reg = 0; 1614 u8_t func = 0; 1615 1616 /* We clear locks due to error recover possible failure leaving locking traces... 1617 * we do this only for E2 and above */ 1618 if (CHIP_IS_E1x(pdev)) 1619 { 1620 return; 1621 } 1622 1623 for (func = 0; func < MAX_FUNC_NUM; func++) 1624 { 1625 DbgBreakIf(func >= ARRSIZE(lm_hw_lock_table)); 1626 hw_lock_cntr_reg = lm_hw_lock_table[func]; 1627 1628 lock_status = REG_RD(pdev, hw_lock_cntr_reg); 1629 if (lock_status != 0) 1630 { 1631 REG_WR(pdev, hw_lock_cntr_reg, lock_status); 1632 } 1633 } 1634 } 1635 1636 u32_t reg_wait_verify_val(struct _lm_device_t * pdev, u32_t reg_offset, u32_t excpected_val, u32_t total_wait_time_ms ) 1637 { 1638 u32_t val = 0 ; 1639 u32_t wait_cnt = 0 ; 1640 u32_t wait_cnt_limit = total_wait_time_ms/DEFAULT_WAIT_INTERVAL_MICSEC ; 1641 if( wait_cnt_limit == 0 ) 1642 { 1643 wait_cnt_limit = 1; 1644 } 1645 val=REG_RD(pdev,reg_offset); 1646 while( (val != excpected_val) && (wait_cnt++ != wait_cnt_limit) ) 1647 { 1648 mm_wait(pdev, DEFAULT_WAIT_INTERVAL_MICSEC) ; 1649 val=REG_RD(pdev,reg_offset); 1650 } 1651 if (val != excpected_val) { 1652 DbgMessage(pdev, WARN, "val = 0x%x, expected val = 0x%x\n", val, excpected_val ); 1653 DbgBreakIf(val != excpected_val); 1654 } 1655 return wait_cnt; 1656 } 1657 1658 /******************************************************************************* 1659 * Description: 1660 * stop any dma transactions to/from chip 1661 * after this function is called, no write to chip is availalbe anymore. 1662 * Return: 1663 * void 1664 ******************************************************************************/ 1665 void lm_disable_pci_dma(struct _lm_device_t *pdev, u8_t b_wait_for_done) 1666 { 1667 u32_t val = 0; 1668 u32_t idx = 0; 1669 const u32_t flags = (PCICFG_DEVICE_STATUS_NO_PEND << 16) ; 1670 1671 if (IS_PFDEV(pdev)) 1672 { 1673 if (CHIP_IS_E1x(pdev)) 1674 { 1675 /* Disable bus_master. */ 1676 val=REG_RD(pdev,GRCBASE_PCICONFIG+PCICFG_COMMAND_OFFSET); 1677 RESET_FLAGS( val, PCICFG_COMMAND_BUS_MASTER ); 1678 REG_WR(pdev,GRCBASE_PCICONFIG+PCICFG_COMMAND_OFFSET,val); 1679 } 1680 else 1681 { 1682 /* In E2, there is a cleaner way to disable pci-dma, no need for a pci-configuration 1683 * transaction */ 1684 REG_WR(pdev, PGLUE_B_REG_INTERNAL_PFID_ENABLE_MASTER, 0); 1685 } 1686 1687 /* wait until there is no pending transaction. */ 1688 if (b_wait_for_done) 1689 { 1690 for(idx = 0; idx < 1000; idx++) 1691 { 1692 val=REG_RD(pdev,GRCBASE_PCICONFIG+PCICFG_DEVICE_CONTROL); 1693 if( (val & flags) == 0) 1694 { 1695 break; 1696 } 1697 mm_wait(pdev, 5); 1698 } 1699 } 1700 } 1701 } 1702 /******************************************************************************* 1703 * Description: 1704 * enable Bus Master Enable 1705 * Return: 1706 * void 1707 ******************************************************************************/ 1708 void lm_enable_pci_dma(struct _lm_device_t *pdev) 1709 { 1710 u32_t val = 0; 1711 if (IS_PFDEV(pdev)) 1712 { 1713 if (CHIP_IS_E1x(pdev)) 1714 { 1715 /* Enable bus_master. */ 1716 val=REG_RD(pdev,GRCBASE_PCICONFIG+PCICFG_COMMAND_OFFSET); 1717 if( 0 == GET_FLAGS( val, PCICFG_COMMAND_BUS_MASTER ) ) 1718 { 1719 SET_FLAGS( val, PCICFG_COMMAND_BUS_MASTER ); 1720 REG_WR(pdev,GRCBASE_PCICONFIG+PCICFG_COMMAND_OFFSET,val); 1721 } 1722 } 1723 else 1724 { 1725 /* In E2, there is a cleaner way to disable pci-dma, no need for a pci-configuration 1726 * transaction */ 1727 REG_WR(pdev, PGLUE_B_REG_INTERNAL_PFID_ENABLE_MASTER, 1); 1728 } 1729 } 1730 } 1731 /******************************************************************************* 1732 * Description: 1733 * disable non fatal error pcie reporting 1734 * Return: 1735 * void 1736 ******************************************************************************/ 1737 void lm_set_pcie_nfe_report(lm_device_t *pdev) 1738 { 1739 if(IS_PFDEV(pdev) && pdev->params.disable_pcie_nfr) 1740 { 1741 u32_t pci_devctl = 0 ; 1742 pci_devctl = REG_RD(pdev,GRCBASE_PCICONFIG + PCICFG_DEVICE_CONTROL); 1743 RESET_FLAGS( pci_devctl, PCICFG_DEVICE_STATUS_NON_FATAL_ERR_DET ); 1744 REG_WR(pdev,GRCBASE_PCICONFIG + PCICFG_DEVICE_CONTROL,pci_devctl); 1745 } 1746 } 1747 1748 // These lm_reg_xx_ind_imp() are for blk reading when lock is acquired only once (for the whole block reading) 1749 void 1750 lm_reg_rd_ind_imp( 1751 lm_device_t *pdev, 1752 u32_t offset, 1753 u32_t *ret) 1754 { 1755 DbgBreakIf(offset & 0x3); 1756 mm_write_pci(pdev,PCICFG_GRC_ADDRESS,offset); 1757 mm_read_pci(pdev,PCICFG_GRC_DATA,ret); 1758 } /* lm_reg_rd_ind_imp */ 1759 void 1760 lm_reg_wr_ind_imp( 1761 lm_device_t *pdev, 1762 u32_t offset, 1763 u32_t val) 1764 { 1765 u32_t dummy; 1766 DbgBreakIf(offset & 0x3); 1767 mm_write_pci(pdev,PCICFG_GRC_ADDRESS,offset); 1768 mm_write_pci(pdev,PCICFG_GRC_DATA,val); 1769 lm_reg_rd_ind_imp(pdev,PCICFG_VENDOR_ID_OFFSET,&dummy); 1770 } /* lm_reg_wr_ind_imp */ 1771 /******************************************************************************* 1772 * Description: 1773 * 1774 * Return: 1775 * None. 1776 * 1777 * Note: 1778 * The caller is responsible for synchronizing calls to lm_reg_rd_ind and 1779 * lm_reg_wr_ind. 1780 ******************************************************************************/ 1781 void 1782 lm_reg_rd_ind( 1783 lm_device_t *pdev, 1784 u32_t offset, 1785 u32_t *ret) 1786 { 1787 MM_ACQUIRE_IND_REG_LOCK(pdev); 1788 lm_reg_rd_ind_imp(pdev,offset,ret); 1789 MM_RELEASE_IND_REG_LOCK(pdev); 1790 } /* lm_reg_rd_ind */ 1791 /******************************************************************************* 1792 * Description: 1793 * 1794 * Return: 1795 * None. 1796 * 1797 * Note: 1798 * The caller is responsible for synchronizing calls to lm_reg_rd_ind and 1799 * lm_reg_wr_ind. 1800 ******************************************************************************/ 1801 void 1802 lm_reg_wr_ind( 1803 lm_device_t *pdev, 1804 u32_t offset, 1805 u32_t val) 1806 { 1807 MM_ACQUIRE_IND_REG_LOCK(pdev); 1808 lm_reg_wr_ind_imp(pdev,offset,val); 1809 MM_RELEASE_IND_REG_LOCK(pdev); 1810 } /* lm_reg_wr_ind */ 1811 /******************************************************************************* 1812 * Description: 1813 * 1814 * Return: 1815 ******************************************************************************/ 1816 void 1817 lm_reg_rd_blk( 1818 lm_device_t *pdev, 1819 u32_t reg_offset, 1820 u32_t *buf_ptr, 1821 u32_t u32t_cnt) 1822 { 1823 u32_t current_offset = 0; 1824 DbgBreakIf(reg_offset & 0x3); 1825 while(u32t_cnt) 1826 { 1827 *buf_ptr = REG_RD(pdev, reg_offset + current_offset); 1828 buf_ptr++; 1829 u32t_cnt--; 1830 current_offset += 4; 1831 } 1832 } /* lm_reg_rd_blk */ 1833 /******************************************************************************* 1834 * Description: 1835 * 1836 * Return: 1837 ******************************************************************************/ 1838 void 1839 lm_reg_rd_blk_ind( 1840 lm_device_t *pdev, 1841 u32_t reg_offset, 1842 u32_t *buf_ptr, 1843 u32_t u32t_cnt, 1844 u8_t acquire_lock_flag) 1845 { 1846 u32_t current_offset = 0; 1847 if(acquire_lock_flag) 1848 { 1849 MM_ACQUIRE_IND_REG_LOCK(pdev); 1850 } 1851 while(u32t_cnt) 1852 { 1853 lm_reg_rd_ind_imp(pdev, reg_offset + current_offset, buf_ptr); 1854 buf_ptr++; 1855 u32t_cnt--; 1856 current_offset += 4; 1857 } 1858 if(acquire_lock_flag) 1859 { 1860 MM_RELEASE_IND_REG_LOCK(pdev); 1861 } 1862 } /* lm_reg_rd_blk_ind */ 1863 1864 /******************************************************************************* 1865 * Description: 1866 * 1867 * Return: 1868 ******************************************************************************/ 1869 void 1870 lm_reg_wr_blk( 1871 lm_device_t *pdev, 1872 u32_t reg_offset, 1873 u32_t *data_ptr, 1874 u32_t u32t_cnt) 1875 { 1876 u32_t current_offset = 0; 1877 DbgBreakIf(reg_offset & 0x3); 1878 while(u32t_cnt) 1879 { 1880 REG_WR(pdev, reg_offset + current_offset, *data_ptr); 1881 data_ptr++; 1882 u32t_cnt--; 1883 current_offset += 4; 1884 } 1885 } /* lm_reg_wr_blk */ 1886 1887 /******************************************************************************* 1888 * Description: 1889 * 1890 * Return: 1891 ******************************************************************************/ 1892 void 1893 lm_reg_wr_blk_ind( 1894 lm_device_t *pdev, 1895 u32_t reg_offset, 1896 u32_t *data_ptr, 1897 u32_t u32t_cnt) 1898 { 1899 u32_t current_offset = 0; 1900 1901 MM_ACQUIRE_IND_REG_LOCK(pdev); 1902 while(u32t_cnt) 1903 { 1904 lm_reg_wr_ind_imp(pdev, reg_offset + current_offset, *data_ptr); 1905 data_ptr++; 1906 u32t_cnt--; 1907 current_offset += 4; 1908 } 1909 MM_RELEASE_IND_REG_LOCK(pdev); 1910 } /* lm_reg_wr_blk_ind */ 1911 1912 void lm_set_waitp(lm_device_t *pdev) 1913 { 1914 REG_WR(pdev,DRV_DUMP_TSTORM_WAITP_ADDRESS,1); 1915 REG_WR(pdev,DRV_DUMP_XSTORM_WAITP_ADDRESS,1); 1916 REG_WR(pdev,DRV_DUMP_CSTORM_WAITP_ADDRESS,1); 1917 REG_WR(pdev,DRV_DUMP_USTORM_WAITP_ADDRESS,1); 1918 } 1919 1920 void lm_collect_idle_storms_dorrbell_asserts( struct _lm_device_t *pdev, 1921 const u8_t b_idle_chk, 1922 const u8_t b_storms_asserts, 1923 const u8_t b_dorrbell_info ) 1924 { 1925 #if !(defined(UEFI) || defined(DOS) || defined(__LINUX)) 1926 if( b_idle_chk ) 1927 { 1928 lm_idle_chk(pdev); 1929 } 1930 1931 if( b_dorrbell_info ) 1932 { 1933 lm_get_doorbell_info(pdev); 1934 } 1935 1936 if( b_storms_asserts ) 1937 { 1938 lm_get_storms_assert(pdev); 1939 } 1940 #endif 1941 } 1942