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
lm_cmng_init(struct _lm_device_t * pdev,u32_t port_rate)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 */
lm_initialize_nig_entry(lm_device_t * pdev,u8_t offset,u8_t * addr)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 */
lm_get_available_nig_entry(lm_device_t * pdev)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 */
lm_find_nig_entry_for_addr(lm_device_t * pdev,u8_t * addr)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
lm_insert_nig_entry(lm_device_t * pdev,u8_t * addr)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 */
lm_remove_nig_entry(lm_device_t * pdev,u8_t * addr)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
lm_setup_fan_failure_detection(struct _lm_device_t * pdev)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 */
lm_gpio_read(struct _lm_device_t * pdev,u32_t pin_num,u32_t * value_ptr,u8_t port)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 */
lm_gpio_write(struct _lm_device_t * pdev,u32_t pin_num,u32_t mode,u8_t port)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 */
lm_gpio_mult_write(struct _lm_device_t * pdev,u8_t pins,u32_t mode)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
lm_gpio_int_write(struct _lm_device_t * pdev,u32_t pin_num,u32_t mode,u8_t port)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 */
lm_spio_read(struct _lm_device_t * pdev,u32_t pin_num,u32_t * value_ptr)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 */
lm_spio_write(struct _lm_device_t * pdev,u32_t pin_num,u32_t value)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 */
lm_set_led_mode(struct _lm_device_t * pdev,u32_t port_idx,u32_t mode_idx)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 */
lm_get_led_mode(struct _lm_device_t * pdev,u32_t port_idx,u32_t * mode_idx_ptr)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 */
lm_override_led_value(struct _lm_device_t * pdev,u32_t port_idx,u32_t led_idx,u32_t value)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 */
lm_blink_traffic_led(struct _lm_device_t * pdev,u32_t port_idx,u32_t rate)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 */
lm_get_led_status(struct _lm_device_t * pdev,u32_t port_idx,u32_t led_idx,u32_t * value_ptr)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
lm_reset_led(struct _lm_device_t * pdev)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
lm_is_57710A0_dbg_intr(struct _lm_device_t * pdev)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 */
lm_57710A0_dbg_intr(struct _lm_device_t * pdev)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
lm_set_led_wrapper(struct _lm_device_t * pdev,const u8_t led_mode)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
lm_get_transceiver_data(struct _lm_device_t * pdev,b10_transceiver_data_t * b10_transceiver_data)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
lm_set_mac_in_nig(lm_device_t * pdev,u8_t * mac_addr,lm_cli_idx_t lm_cli_idx,u8_t offset)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 ******************************************************************************/
lm_hw_lock(lm_device_t * pdev,const u32_t resource,const u8_t b_block)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 ******************************************************************************/
lm_hw_unlock_ex(lm_device_t * pdev,const u32_t resource,const u8_t b_verify_locked)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 ******************************************************************************/
lm_hw_unlock(lm_device_t * pdev,const u32_t resource)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 */
lm_hw_clear_all_locks(lm_device_t * pdev)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
reg_wait_verify_val(struct _lm_device_t * pdev,u32_t reg_offset,u32_t excpected_val,u32_t total_wait_time_ms)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 ******************************************************************************/
lm_disable_pci_dma(struct _lm_device_t * pdev,u8_t b_wait_for_done)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 ******************************************************************************/
lm_enable_pci_dma(struct _lm_device_t * pdev)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 ******************************************************************************/
lm_set_pcie_nfe_report(lm_device_t * pdev)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
lm_reg_rd_ind_imp(lm_device_t * pdev,u32_t offset,u32_t * ret)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
lm_reg_wr_ind_imp(lm_device_t * pdev,u32_t offset,u32_t val)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
lm_reg_rd_ind(lm_device_t * pdev,u32_t offset,u32_t * ret)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
lm_reg_wr_ind(lm_device_t * pdev,u32_t offset,u32_t val)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
lm_reg_rd_blk(lm_device_t * pdev,u32_t reg_offset,u32_t * buf_ptr,u32_t u32t_cnt)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
lm_reg_rd_blk_ind(lm_device_t * pdev,u32_t reg_offset,u32_t * buf_ptr,u32_t u32t_cnt,u8_t acquire_lock_flag)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
lm_reg_wr_blk(lm_device_t * pdev,u32_t reg_offset,u32_t * data_ptr,u32_t u32t_cnt)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
lm_reg_wr_blk_ind(lm_device_t * pdev,u32_t reg_offset,u32_t * data_ptr,u32_t u32t_cnt)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
lm_set_waitp(lm_device_t * pdev)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
lm_collect_idle_storms_dorrbell_asserts(struct _lm_device_t * pdev,const u8_t b_idle_chk,const u8_t b_storms_asserts,const u8_t b_dorrbell_info)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