1 /*
2 * Copyright 2014-2017 Cavium, Inc.
3 * The contents of this file are subject to the terms of the Common Development
4 * and Distribution License, v.1, (the "License").
5 *
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the License at available
9 * at http://opensource.org/licenses/CDDL-1.0
10 *
11 * See the License for the specific language governing permissions and
12 * limitations under the License.
13 */
14
15 #include "lm5706.h"
16
17
18
19 /*******************************************************************************
20 * Description:
21 *
22 * Return:
23 ******************************************************************************/
24 lm_status_t
lm_set_mac_addr(lm_device_t * pdev,u32_t addr_idx,u8_t * mac_addr)25 lm_set_mac_addr(
26 lm_device_t *pdev,
27 u32_t addr_idx,
28 u8_t *mac_addr)
29 {
30 u32_t val;
31
32 if(addr_idx >= 16)
33 {
34 DbgBreakMsg("Invalid mac address index.\n");
35
36 return LM_STATUS_FAILURE;
37 }
38
39 val = (mac_addr[0]<<8) | mac_addr[1];
40 REG_WR(pdev, emac.emac_mac_match[addr_idx*2], val);
41
42 val = (mac_addr[2]<<24) | (mac_addr[3]<<16) |
43 (mac_addr[4]<<8) | mac_addr[5];
44 REG_WR(pdev, emac.emac_mac_match[addr_idx*2+1], val);
45
46 return LM_STATUS_SUCCESS;
47 } /* lm_set_mac_addr */
48
49
50
51 /*******************************************************************************
52 * Description:
53 *
54 * Return:
55 * None.
56 *
57 * Note:
58 * The caller is responsible for synchronizing calls to lm_reg_rd_ind and
59 * lm_reg_wr_ind.
60 ******************************************************************************/
61 void
lm_reg_rd_ind(lm_device_t * pdev,u32_t offset,u32_t * ret)62 lm_reg_rd_ind(
63 lm_device_t *pdev,
64 u32_t offset,
65 u32_t *ret)
66 {
67 /* DbgBreakIf(offset & 0x3); // this can occur for some shmem accesses */
68
69 mm_acquire_ind_reg_lock(pdev);
70
71 REG_WR(pdev, pci_config.pcicfg_reg_window_address, offset);
72 REG_RD(pdev, pci_config.pcicfg_reg_window, ret);
73
74 mm_release_ind_reg_lock(pdev);
75 } /* lm_reg_rd_ind */
76
77
78
79 /*******************************************************************************
80 * Description:
81 *
82 * Return:
83 * None.
84 *
85 * Note:
86 * The caller is responsible for synchronizing calls to lm_reg_rd_ind and
87 * lm_reg_wr_ind.
88 ******************************************************************************/
89 void
lm_reg_wr_ind(lm_device_t * pdev,u32_t offset,u32_t val)90 lm_reg_wr_ind(
91 lm_device_t *pdev,
92 u32_t offset,
93 u32_t val)
94 {
95 DbgBreakIf(offset & 0x3);
96
97 mm_acquire_ind_reg_lock(pdev);
98
99 REG_WR(pdev, pci_config.pcicfg_reg_window_address, offset);
100 REG_WR(pdev, pci_config.pcicfg_reg_window, val);
101
102 mm_release_ind_reg_lock(pdev);
103 } /* lm_reg_wr_ind */
104
105
106
107 /*******************************************************************************
108 * Description:
109 *
110 * Return:
111 ******************************************************************************/
112 void
lm_ctx_wr(lm_device_t * pdev,u32_t cid_addr,u32_t offset,u32_t val)113 lm_ctx_wr(
114 lm_device_t *pdev,
115 u32_t cid_addr,
116 u32_t offset,
117 u32_t val)
118 {
119 u32_t retry_cnt;
120 u32_t idx;
121
122 DbgBreakIf(cid_addr > MAX_CID_ADDR || offset & 0x3 || cid_addr & CTX_MASK);
123
124 offset += cid_addr;
125
126 if(CHIP_NUM(pdev) == CHIP_NUM_5709)
127 {
128 if (CHIP_REV(pdev) == CHIP_REV_IKOS)
129 {
130 retry_cnt = 2000;
131 }
132 else
133 {
134 retry_cnt = 250;
135 }
136
137 REG_WR(pdev, context.ctx_ctx_data, val);
138 REG_WR(pdev, context.ctx_ctx_ctrl, offset | CTX_CTX_CTRL_WRITE_REQ);
139
140 for(idx=0; idx < retry_cnt; idx++)
141 {
142 REG_RD(pdev, context.ctx_ctx_ctrl, &val);
143
144 if((val & CTX_CTX_CTRL_WRITE_REQ) == 0)
145 {
146 break;
147 }
148
149 mm_wait(pdev, 10);
150 }
151
152 DbgBreakIf(idx == retry_cnt);
153 }
154 else
155 {
156 REG_WR(pdev, context.ctx_data_adr, offset);
157 REG_WR(pdev, context.ctx_data, val);
158 }
159 } /* lm_ctx_wr */
160
161
162
163 /*******************************************************************************
164 * Description:
165 *
166 * Return:
167 ******************************************************************************/
168 u32_t
lm_ctx_rd(lm_device_t * pdev,u32_t cid_addr,u32_t offset)169 lm_ctx_rd(
170 lm_device_t *pdev,
171 u32_t cid_addr,
172 u32_t offset)
173 {
174 u32_t retry_cnt;
175 u32_t val;
176 u32_t idx;
177
178 DbgBreakIf(cid_addr > MAX_CID_ADDR || offset & 0x3 || cid_addr & CTX_MASK);
179
180 offset += cid_addr;
181
182 if(CHIP_NUM(pdev) == CHIP_NUM_5709)
183 {
184 if(CHIP_REV(pdev) == CHIP_REV_IKOS)
185 {
186 retry_cnt = 1000;
187 }
188 else
189 {
190 retry_cnt = 25;
191 }
192
193 REG_WR(pdev, context.ctx_ctx_ctrl, offset | CTX_CTX_CTRL_READ_REQ);
194
195 for(idx = 0; idx < retry_cnt; idx++)
196 {
197 REG_RD(pdev, context.ctx_ctx_ctrl, &val);
198
199 if((val & CTX_CTX_CTRL_READ_REQ) == 0)
200 {
201 break;
202 }
203
204 mm_wait(pdev, 5);
205 }
206
207 DbgBreakIf(idx == retry_cnt);
208
209 REG_RD(pdev, context.ctx_ctx_data, &val);
210 }
211 else
212 {
213 REG_WR(pdev, context.ctx_data_adr, offset);
214 REG_RD(pdev, context.ctx_data, &val);
215 }
216
217 return val;
218 } /* lm_ctx_rd */
219
220
221
222 /*******************************************************************************
223 * Description:
224 *
225 * Return:
226 ******************************************************************************/
227 void
lm_disable_int(lm_device_t * pdev)228 lm_disable_int(
229 lm_device_t *pdev)
230 {
231 u32_t sb_idx;
232 u32_t val;
233
234 switch(CHIP_NUM(pdev))
235 {
236 case CHIP_NUM_5706:
237 case CHIP_NUM_5708:
238 REG_RD(pdev, pci_config.pcicfg_int_ack_cmd, &val);
239 val |= PCICFG_INT_ACK_CMD_MASK_INT;
240 REG_WR(pdev, pci_config.pcicfg_int_ack_cmd, val);
241 break;
242
243 case CHIP_NUM_5709:
244 for(sb_idx = 0; sb_idx < 9; sb_idx++)
245 {
246 val = PCICFG_INT_ACK_CMD_MASK_INT | (sb_idx << 24);
247 REG_WR(pdev, pci_config.pcicfg_int_ack_cmd, val);
248 }
249 break;
250
251 default:
252 DbgBreakMsg("Unsupported chip.\n");
253 break;
254 }
255 } /* lm_disable_int */
256
257
258
259 /*******************************************************************************
260 * Description:
261 *
262 * Return:
263 ******************************************************************************/
264 void
lm_enable_int(lm_device_t * pdev)265 lm_enable_int(
266 lm_device_t *pdev)
267 {
268 u32_t val;
269
270 switch(CHIP_NUM(pdev))
271 {
272 case CHIP_NUM_5706:
273 case CHIP_NUM_5708:
274 REG_RD(pdev, pci_config.pcicfg_int_ack_cmd, &val);
275 val &= ~PCICFG_INT_ACK_CMD_MASK_INT;
276 REG_WR(pdev, pci_config.pcicfg_int_ack_cmd, val);
277 break;
278
279 case CHIP_NUM_5709:
280 REG_RD(pdev, hc.hc_config, &val);
281 val |= HC_CONFIG_UNMASK_ALL;
282 REG_WR(pdev, hc.hc_config, val);
283 break;
284
285 default:
286 DbgBreakMsg("Unsupported chip.\n");
287 break;
288 }
289 } /* lm_enable_int */
290
291
292
293 /*******************************************************************************
294 * Description:
295 *
296 * Return:
297 ******************************************************************************/
298 void
lm_reg_rd_blk(lm_device_t * pdev,u32_t reg_offset,u32_t * buf_ptr,u32_t u32t_cnt)299 lm_reg_rd_blk(
300 lm_device_t *pdev,
301 u32_t reg_offset,
302 u32_t *buf_ptr,
303 u32_t u32t_cnt)
304 {
305 u32_t grc_win_offset;
306 u32_t grc_win_base;
307
308 DbgBreakIf(reg_offset & 0x3);
309
310 grc_win_offset = reg_offset & (GRC_WINDOW_SIZE - 1);
311 grc_win_base = reg_offset & ~(GRC_WINDOW_SIZE - 1);
312
313 REG_WR(pdev, pci.pci_grc_window_addr, grc_win_base);
314
315 while(u32t_cnt)
316 {
317 if(grc_win_offset >= GRC_WINDOW_SIZE)
318 {
319 grc_win_offset = 0;
320 grc_win_base += GRC_WINDOW_SIZE;
321
322 REG_WR(pdev, pci.pci_grc_window_addr, grc_win_base);
323 }
324
325 REG_RD_OFFSET(pdev, GRC_WINDOW_BASE + grc_win_offset, buf_ptr);
326
327 buf_ptr++;
328 u32t_cnt--;
329 grc_win_offset += 4;
330 }
331
332 REG_WR(pdev, pci.pci_grc_window_addr, pdev->hw_info.shmem_base & ~0x7fff);
333 } /* lm_reg_rd_blk */
334
335
336
337 /*******************************************************************************
338 * Description:
339 *
340 * Return:
341 ******************************************************************************/
342 void
lm_reg_rd_blk_ind(lm_device_t * pdev,u32_t reg_offset,u32_t * buf_ptr,u32_t u32t_cnt)343 lm_reg_rd_blk_ind(
344 lm_device_t *pdev,
345 u32_t reg_offset,
346 u32_t *buf_ptr,
347 u32_t u32t_cnt)
348 {
349 DbgBreakIf(reg_offset & 0x3);
350
351 mm_acquire_ind_reg_lock(pdev);
352
353 while(u32t_cnt)
354 {
355 REG_WR(pdev, pci_config.pcicfg_reg_window_address, reg_offset);
356 REG_RD(pdev, pci_config.pcicfg_reg_window, buf_ptr);
357
358 buf_ptr++;
359 u32t_cnt--;
360 reg_offset += 4;
361 }
362
363 mm_release_ind_reg_lock(pdev);
364 } /* lm_reg_rd_blk_ind */
365
366
367
368 /*******************************************************************************
369 * Description:
370 *
371 * Return:
372 ******************************************************************************/
373 void
lm_reg_wr_blk(lm_device_t * pdev,u32_t reg_offset,u32_t * data_ptr,u32_t u32t_cnt)374 lm_reg_wr_blk(
375 lm_device_t *pdev,
376 u32_t reg_offset,
377 u32_t *data_ptr,
378 u32_t u32t_cnt)
379 {
380 u32_t grc_win_offset;
381 u32_t grc_win_base;
382 u32_t grc_win_size;
383
384 DbgBreakIf(reg_offset & 0x3);
385
386 if (CHIP_NUM(pdev) == CHIP_NUM_5709)
387 {
388 grc_win_size = GRC_WINDOW_SIZE / 4;
389 }
390 else
391 {
392 grc_win_size = GRC_WINDOW_SIZE;
393 }
394
395 grc_win_offset = reg_offset & (grc_win_size - 1);
396 grc_win_base = reg_offset & ~(grc_win_size - 1);
397
398 REG_WR(pdev, pci.pci_grc_window_addr, grc_win_base);
399
400 while(u32t_cnt)
401 {
402 if(grc_win_offset >= grc_win_size)
403 {
404 grc_win_offset = 0;
405 grc_win_base += grc_win_size;
406
407 REG_WR(pdev, pci.pci_grc_window_addr, grc_win_base);
408 }
409
410 REG_WR_OFFSET(pdev, GRC_WINDOW_BASE + grc_win_offset, *data_ptr);
411
412 data_ptr++;
413 u32t_cnt--;
414 grc_win_offset += 4;
415 }
416
417 REG_WR(pdev, pci.pci_grc_window_addr, pdev->hw_info.shmem_base & ~0x7fff);
418 } /* lm_reg_wr_blk */
419
420
421
422 /*******************************************************************************
423 * Description:
424 *
425 * Return:
426 ******************************************************************************/
427 void
lm_reg_wr_blk_ind(lm_device_t * pdev,u32_t reg_offset,u32_t * data_ptr,u32_t u32t_cnt)428 lm_reg_wr_blk_ind(
429 lm_device_t *pdev,
430 u32_t reg_offset,
431 u32_t *data_ptr,
432 u32_t u32t_cnt)
433 {
434 DbgBreakIf(reg_offset & 0x3);
435
436 mm_acquire_ind_reg_lock(pdev);
437
438 while(u32t_cnt)
439 {
440 REG_WR(pdev, pci_config.pcicfg_reg_window_address, reg_offset);
441 REG_WR(pdev, pci_config.pcicfg_reg_window, *data_ptr);
442
443 data_ptr++;
444 u32t_cnt--;
445 reg_offset += 4;
446 }
447
448 mm_release_ind_reg_lock(pdev);
449 } /* lm_reg_wr_blk_ind */
450
451
452
453 /*******************************************************************************
454 * Description:
455 *
456 * Return:
457 ******************************************************************************/
458 lm_status_t
lm_submit_fw_cmd(lm_device_t * pdev,u32_t drv_msg)459 lm_submit_fw_cmd(
460 lm_device_t *pdev,
461 u32_t drv_msg)
462 {
463 u32_t val;
464
465 if(pdev->vars.fw_timed_out)
466 {
467 DbgMessage(pdev, WARN, "fw timed out.\n");
468
469 return LM_STATUS_FAILURE;
470 }
471
472 DbgBreakIf(drv_msg & 0xffff);
473
474 REG_RD_IND(
475 pdev,
476 pdev->hw_info.shmem_base + OFFSETOF(shmem_region_t, drv_fw_mb.fw_mb),
477 &val);
478 if((val & FW_MSG_ACK) != (pdev->vars.fw_wr_seq & DRV_MSG_SEQ))
479 {
480 DbgMessage(pdev, WARN, "command pending.\n");
481
482 return LM_STATUS_FAILURE;
483 }
484
485 pdev->vars.fw_wr_seq++;
486
487 drv_msg |= (pdev->vars.fw_wr_seq & DRV_MSG_SEQ);
488
489 REG_WR_IND(
490 pdev,
491 pdev->hw_info.shmem_base +
492 OFFSETOF(shmem_region_t, drv_fw_mb.drv_mb),
493 drv_msg);
494
495 return LM_STATUS_SUCCESS;
496 } /* lm_submit_fw_cmd */
497
498
499
500 /*******************************************************************************
501 * Description:
502 *
503 * Return:
504 ******************************************************************************/
505 lm_status_t
lm_last_fw_cmd_status(lm_device_t * pdev)506 lm_last_fw_cmd_status(
507 lm_device_t *pdev)
508 {
509 u32_t val;
510
511 if(pdev->vars.fw_timed_out)
512 {
513 DbgMessage(pdev, WARN, "fw timed out.\n");
514
515 return LM_STATUS_TIMEOUT;
516 }
517
518 REG_RD_IND(
519 pdev,
520 pdev->hw_info.shmem_base +
521 OFFSETOF(shmem_region_t, drv_fw_mb.fw_mb),
522 &val);
523 if((val & FW_MSG_ACK) != (pdev->vars.fw_wr_seq & DRV_MSG_SEQ))
524 {
525 return LM_STATUS_BUSY;
526 }
527
528 if((val & FW_MSG_STATUS_MASK) != FW_MSG_STATUS_OK)
529 {
530 return LM_STATUS_FAILURE;
531 }
532
533 return LM_STATUS_SUCCESS;
534 } /* lm_last_fw_cmd_status */
535
536
537
538 /*******************************************************************************
539 * Description:
540 *
541 * Return:
542 ******************************************************************************/
543 u32_t
lm_mb_get_cid_addr(lm_device_t * pdev,u32_t cid)544 lm_mb_get_cid_addr(
545 lm_device_t *pdev,
546 u32_t cid)
547 {
548 u32_t mq_offset;
549
550 DbgBreakIf(pdev->params.bin_mq_mode && CHIP_NUM(pdev) != CHIP_NUM_5709);
551
552 if(cid < 256 || pdev->params.bin_mq_mode == FALSE)
553 {
554 mq_offset = 0x10000 + (cid << MB_KERNEL_CTX_SHIFT);
555 }
556 else
557 {
558 DbgBreakIf(cid < pdev->hw_info.first_l4_l5_bin);
559
560 mq_offset = 0x10000 +
561 ((((cid - pdev->hw_info.first_l4_l5_bin) /
562 pdev->hw_info.bin_size) + 256) << MB_KERNEL_CTX_SHIFT);
563 }
564
565 DbgBreakIf(mq_offset > pdev->hw_info.bar_size);
566
567 return mq_offset;
568 } /* lm_mb_get_cid_addr */
569
570
571
572 /*******************************************************************************
573 * Description:
574 *
575 * Return:
576 ******************************************************************************/
577 u32_t
lm_mb_get_bypass_addr(lm_device_t * pdev,u32_t cid)578 lm_mb_get_bypass_addr(
579 lm_device_t *pdev,
580 u32_t cid)
581 {
582 u32_t mq_offset;
583
584 DbgBreakIf(pdev->params.bin_mq_mode && CHIP_NUM(pdev) != CHIP_NUM_5709);
585
586 if(cid < 256 || pdev->params.bin_mq_mode == FALSE)
587 {
588 mq_offset = 0x10000 +
589 MB_KERNEL_CTX_SIZE * MAX_CID_CNT +
590 cid * LM_PAGE_SIZE;
591 }
592 else
593 {
594 DbgBreakIf(cid < pdev->hw_info.first_l4_l5_bin);
595
596 mq_offset = 0x10000 +
597 MB_KERNEL_CTX_SIZE * MAX_CID_CNT +
598 (((cid - pdev->hw_info.first_l4_l5_bin) /
599 pdev->hw_info.bin_size) + 256) * LM_PAGE_SIZE;
600 }
601
602 DbgBreakIf(mq_offset > pdev->hw_info.bar_size);
603
604 return mq_offset;
605 } /* lm_mb_get_bypass_addr */
606
607