1/* ********************************************************************* 2 * Broadcom Common Firmware Environment (CFE) 3 * 4 * HSP Configuration file File: bcm1480_hsp_utils.c 5 * 6 * This file contains initalization and configuration routines for 7 * the BCM1480 High Speed Port Interface. This routine will 8 * be responsible for managing the allocation of TX/RX buffer space 9 * and initialization of associate -phil cnt' registers. 10 * 11 * This file have been originally developed under the CFE environment. 12 * 13 * Code was leveraged from 'bcm1480_pci_machdep.c' and 'ui_pmcmd.c' 14 * 15 * Author: Kean Hurley 16 * 17 ********************************************************************* 18 * 19 * Copyright 2000,2001,2002,2003,2004,2005,2006 20 * Broadcom Corporation. All rights reserved. 21 * 22 * This software is furnished under license and may be used and 23 * copied only in accordance with the following terms and 24 * conditions. Subject to these conditions, you may download, 25 * copy, install, use, modify and distribute modified or unmodified 26 * copies of this software in source and/or binary form. No title 27 * or ownership is transferred hereby. 28 * 29 * 1) Any source code used, modified or distributed must reproduce 30 * and retain this copyright notice and list of conditions 31 * as they appear in the source file. 32 * 33 * 2) No right is granted to use any trade name, trademark, or 34 * logo of Broadcom Corporation. The "Broadcom Corporation" 35 * name may not be used to endorse or promote products derived 36 * from this software without the prior written permission of 37 * Broadcom Corporation. 38 * 39 * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR 40 * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED 41 * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR 42 * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT 43 * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN 44 * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR DIRECT, INDIRECT, 45 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 46 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 47 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 48 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 49 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR 50 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE), EVEN IF ADVISED OF 51 * THE POSSIBILITY OF SUCH DAMAGE. 52 ********************************************************************* */ 53 54 55/*********************************************************** 56* 57* Included files 58* 59***********************************************************/ 60#include "cfe.h" 61#include "sbmips.h" 62 63#include "lib_physio.h" 64 65#include "pcivar.h" 66#include "pci_internal.h" 67#include "pcireg.h" 68#include "ldtreg.h" 69#include "pci_cfg.h" 70 71#include "bcm1480_regs.h" 72#include "bcm1480_ht.h" 73#include "bcm1480_hsp.h" 74#include "bcm1480_scd.h" 75 76#include "bcm1480_hsp_utils.h" 77 78/*********************************************************** 79* 80* Global variables 81* 82***********************************************************/ 83 84/*********************************************************** 85* 86* Defined values, enumerated types, macros, typedefs 87* internal to this file 88* 89***********************************************************/ 90 91#if 0 // For future allocation manager 92typedef struct bcm1480_hsp_buf_mgr 93{ 94 uint32_t cli_alloc_flags[BCM1480_HT_NUM_PORTS]; 95 uint32_t free_rx_buf_idx[BCM1480_HT_NUM_PORTS]; 96 uint32_t free_tx_buf_idx[BCM1480_HT_NUM_PORTS]; 97} bcm1480_hsp_buf_mgr_t; 98 99typedef struct bcm1480_hsp_io_buf_info 100{ 101 uint32_t rx_npc_cmd_bufs; 102 uint32_t rx_npc_data_bufs; 103 uint32_t rx_pc_cmd_bufs; 104 uint32_t rx_pc_data_bufs; 105 uint32_t rx_rsp_data_bufs; 106 uint32_t tx_npc_bufs; 107 uint32_t tx_pc_bufs; 108 uint32_t tx_rsp_bufs; 109} bcm1480_hsp_buf_io_info_t; 110 111 112typedef struct bcm1480_hsp_ccnuma_buf_info 113{ 114 uint32_t rx_prb_bufs; 115 uint32_t rx_ack_bufs; 116 uint32_t rx_wb_bufs; 117 uint32_t rx_cfill_bufs; 118 uint32_t rx_crd_bufs; 119 uint32_t tx_prb_bufs; 120 uint32_t tx_ack_bufs; 121 uint32_t tx_wb_bufs; 122 uint32_t tx_cfill_bufs; 123 uint32_t tx_crd_bufs; 124} bcm1480_hsp_ccnuma_buf_info_t; 125 126#endif 127 128#define WRITECSR(x,y) phys_write64(x,y) 129#define READCSR(x) phys_read64(x) 130 131#define CALENDAR_M 1 // there is a hw bug--can't have LEN too small 132#define CALENDAR_LEN 16 // we keep this 16 even for fewer channels 133 134#define REFCLK 100 /* in MHz */ 135 136/*********************************************************** 137* 138* Static variables 139* 140***********************************************************/ 141// Documented 142 143 144/*********************************************************** 145* 146* Function prototypes of static functions 147* 148***********************************************************/ 149#ifndef DOXYGEN_IGNORE_ALWAYS 150 151 152#endif 153 154 155/*********************************************************** 156* 157* Functions 158* 159***********************************************************/ 160 161/* 162 * HT port initialization. See Section 13, pp. 479-480. 163 */ 164 165/** 166 @fn hsp_ht_ram_alloc ( uint32_t port ); 167*/ 168void hsp_ht_ram_alloc ( uint32_t port ) 169{ 170 /* HSP: Allocate RX and TX buffers. */ 171 /* NB: Floor and ceiling fields in all ramalloc registers are 172 swapped relative to the original documentation. */ 173 174 /* The following allocations for HT i/o and ccnuma are recommended 175 defaults per PR3491 and PR3492 */ 176 177 WRITECSR(A_BCM1480_HSP_REGISTER(port, R_BCM1480_HSP_RX_HT_RAMALLOC_0), 178 (V_BCM1480_HSP_RX_NPC_CMD_FLOOR(0x300) | 179 V_BCM1480_HSP_RX_NPC_CMD_CEILING(0x307))); 180 181#ifdef _BCM1480_PASS1_WORKAROUNDS_ 182 WRITECSR(A_BCM1480_HSP_REGISTER(port, R_BCM1480_HSP_RX_HT_RAMALLOC_1), 183 (V_BCM1480_HSP_RX_PC_CMD_FLOOR(0x348) | 184 V_BCM1480_HSP_RX_PC_CMD_CEILING(0x34F) | 185 V_BCM1480_HSP_RX_PRB_FLOOR(0x000) | 186 V_BCM1480_HSP_RX_PRB_CEILING(0x000))); 187#else 188 WRITECSR(A_BCM1480_HSP_REGISTER(port, R_BCM1480_HSP_RX_HT_RAMALLOC_1), 189 (V_BCM1480_HSP_RX_PC_CMD_FLOOR(0x348) | 190 V_BCM1480_HSP_RX_PC_CMD_CEILING(0x34F) | 191 V_BCM1480_HSP_RX_PRB_FLOOR(0x378) | 192 V_BCM1480_HSP_RX_PRB_CEILING(0x387))); 193#endif 194 195 WRITECSR(A_BCM1480_HSP_REGISTER(port, R_BCM1480_HSP_RX_HT_RAMALLOC_2), 196 (V_BCM1480_HSP_RX_ACK_FLOOR(0x388) | 197 V_BCM1480_HSP_RX_ACK_CEILING(0x397) | 198 V_BCM1480_HSP_RX_WB_FLOOR(0x398) | 199 V_BCM1480_HSP_RX_WB_CEILING(0x3C1))); 200 WRITECSR(A_BCM1480_HSP_REGISTER(port, R_BCM1480_HSP_RX_HT_RAMALLOC_3), 201 (V_BCM1480_HSP_RX_CFILL_FLOOR(0x3C2) | 202 V_BCM1480_HSP_RX_CFILL_CEILING(0x3EE) | 203 V_BCM1480_HSP_RX_CRD_FLOOR(0x3EF) | 204 V_BCM1480_HSP_RX_CRD_CEILING(0x3FF))); 205 WRITECSR(A_BCM1480_HSP_REGISTER(port, R_BCM1480_HSP_RX_HT_RAMALLOC_4), 206 (V_BCM1480_HSP_RX_NPC_DAT_FLOOR(0x308) | 207 V_BCM1480_HSP_RX_NPC_DAT_CEILING(0x32F) | 208 V_BCM1480_HSP_RX_RSP_DAT_FLOOR(0x330) | 209 V_BCM1480_HSP_RX_RSP_DAT_CEILING(0x347))); 210 WRITECSR(A_BCM1480_HSP_REGISTER(port, R_BCM1480_HSP_RX_HT_RAMALLOC_5), 211 (V_BCM1480_HSP_RX_PC_DAT_FLOOR(0x350) | 212 V_BCM1480_HSP_RX_PC_DAT_CEILING(0x377))); 213 214 WRITECSR(A_BCM1480_HSP_REGISTER(port, R_BCM1480_HSP_TX_NPC_RAMALLOC), 215 V_BCM1480_HSP_TX_NPC_FLOOR(0xC0) | 216 V_BCM1480_HSP_TX_NPC_CEILING(0xC9)); 217 WRITECSR(A_BCM1480_HSP_REGISTER(port, R_BCM1480_HSP_TX_RSP_RAMALLOC), 218 V_BCM1480_HSP_TX_RSP_FLOOR(0xCA) | /* KPH: (D1 - CA) + 1 = 8, which is good */ 219 V_BCM1480_HSP_TX_RSP_CEILING(0xD1)); /* need to be divs by 4 (RSP sz 4*16) */ 220 WRITECSR(A_BCM1480_HSP_REGISTER(port, R_BCM1480_HSP_TX_PC_RAMALLOC), 221 V_BCM1480_HSP_TX_PC_FLOOR(0xD3) | /* KPH: (E1 - D3) + 1 = F, which is good */ 222 V_BCM1480_HSP_TX_PC_CEILING(0xE1)); /* need to be divs by 5 (PC sz 5*16) */ 223 /* D2 unused, but no bigge for now */ 224 WRITECSR(A_BCM1480_HSP_REGISTER(port, R_BCM1480_HSP_TX_HTCC_RAMALLOC_0), 225 V_BCM1480_HSP_TX_PRB_FLOOR(0xE2) | 226 V_BCM1480_HSP_TX_PRB_CEILING(0xE5) | 227 V_BCM1480_HSP_TX_ACK_FLOOR(0xE6) | 228 V_BCM1480_HSP_TX_ACK_CEILING(0xE9)); 229 WRITECSR(A_BCM1480_HSP_REGISTER(port, R_BCM1480_HSP_TX_HTCC_RAMALLOC_1), 230 V_BCM1480_HSP_TX_WB_FLOOR(0xEA) | 231 V_BCM1480_HSP_TX_WB_CEILING(0xF2) | 232 V_BCM1480_HSP_TX_CFILL_FLOOR(0xF3) | 233 V_BCM1480_HSP_TX_CFILL_CEILING(0xFB)); 234 WRITECSR(A_BCM1480_HSP_REGISTER(port, R_BCM1480_HSP_TX_HTCC_RAMALLOC_2), 235 V_BCM1480_HSP_TX_CRD_FLOOR(0xFC) | 236 V_BCM1480_HSP_TX_CRD_CEILING(0xFF)); 237} 238 239 240/** 241 @fn void hsp_ht_ram_alloc ( uint32_t port ); 242*/ 243void hsp_ht_flow_alloc (uint32_t port) 244{ 245 /* HSP: Program the flow control registers. */ 246 247 /* The following allocations for HT i/o and ccnuma are recommended 248 faults per PR3491 and PR3492. */ 249 250 WRITECSR(A_BCM1480_HSP_REGISTER(port, R_BCM1480_HSP_TX_HTIO_RXPHITCNT), 251 (V_BCM1480_HSP_RX_NPC_CMD_PHITCNT(0x08) | 252 V_BCM1480_HSP_RX_NPC_DAT_PHITCNT(0x08) | 253 V_BCM1480_HSP_RX_RSP_DAT_PHITCNT(0x06) | 254 V_BCM1480_HSP_RX_PC_CMD_PHITCNT(0x08) | 255 V_BCM1480_HSP_RX_PC_DAT_PHITCNT(0x08))); 256 257#ifdef _BCM1480_PASS1_WORKAROUNDS_ 258 WRITECSR(A_BCM1480_HSP_REGISTER(port, R_BCM1480_HSP_TX_HTCC_RXPHITCNT), 259 (V_BCM1480_HSP_TX_HTCC_PRB_PHITCNT(0x01) | 260 V_BCM1480_HSP_TX_HTCC_ACK_PHITCNT(0x10) | 261 V_BCM1480_HSP_TX_HTCC_WB_PHITCNT(0x0E) | 262 V_BCM1480_HSP_TX_HTCC_CFILL_PHITCNT(0x0F) | 263 V_BCM1480_HSP_TX_HTCC_CRD_PHITCNT(0x11))); 264#else 265 WRITECSR(A_BCM1480_HSP_REGISTER(port, R_BCM1480_HSP_TX_HTCC_RXPHITCNT), 266 (V_BCM1480_HSP_TX_HTCC_PRB_PHITCNT(0x10) | 267 V_BCM1480_HSP_TX_HTCC_ACK_PHITCNT(0x10) | 268 V_BCM1480_HSP_TX_HTCC_WB_PHITCNT(0x0E) | 269 V_BCM1480_HSP_TX_HTCC_CFILL_PHITCNT(0x0F) | 270 V_BCM1480_HSP_TX_HTCC_CRD_PHITCNT(0x11))); 271#endif 272 273 WRITECSR(A_BCM1480_HSP_REGISTER(port, R_BCM1480_HSP_TX_HTIO_TXPHITCNT), 274 (V_BCM1480_HSP_TX_NPC_PHITCNT(0x0A) | 275 V_BCM1480_HSP_TX_RSP_PHITCNT(0x08) | /* KPH: 2 * (4 RSP sz 4*16) */ 276 V_BCM1480_HSP_TX_PC_PHITCNT(0x0F))); /* KPH: 3 * (5 PC Cmd sz 5*16) */ 277 WRITECSR(A_BCM1480_HSP_REGISTER(port, R_BCM1480_HSP_TX_HTCC_TXPHITCNT), 278 (V_BCM1480_HSP_TX_HTCC_PRB_PHITCNT(0x04) | 279 V_BCM1480_HSP_TX_HTCC_ACK_PHITCNT(0x04) | 280 V_BCM1480_HSP_TX_HTCC_WB_PHITCNT(0x09) | 281 V_BCM1480_HSP_TX_HTCC_CFILL_PHITCNT(0x09) | 282 V_BCM1480_HSP_TX_HTCC_CRD_PHITCNT(0x04))); 283 284 /* mpl: setting POHT up here */ 285 286 WRITECSR(A_BCM1480_HSP_REGISTER(port,R_BCM1480_HSP_RX_PKT_RAMALLOC(0)), 287 V_BCM1480_HSP_RX_RAMCEILING_0(0x03F)| 288 V_BCM1480_HSP_RX_RAMFLOOR_0(0x000)); 289 290 WRITECSR(A_BCM1480_HSP_REGISTER(port,R_BCM1480_HSP_TX_PKT_RAMALLOC(0)), 291 V_BCM1480_HSP_TX_RAMCEILING_0(0x00F)| 292 V_BCM1480_HSP_TX_RAMFLOOR_0(0x000)); 293 294 WRITECSR(A_BCM1480_HSP_REGISTER(port,R_BCM1480_HSP_TX_PKT_RXPHITCNT(0)), 295 V_BCM1480_HSP_RX_PHITCNT_0(0x10)); 296 297 WRITECSR(A_BCM1480_HSP_REGISTER(port,R_BCM1480_HSP_TX_PKT_TXPHITCNT(0)), 298 V_BCM1480_HSP_TX_PHITCNT_0(0x10)); 299} 300 301/** 302 @fn uint32_t hsp_ht_init (void) 303*/ 304uint32_t hsp_ht_init (void) 305{ 306 int i; 307 unsigned int ht_map; 308 309 /* HSP: Discover the ports in HT mode. */ 310 ht_map = 0; 311 for (i = 0; i < BCM1480_HT_NUM_PORTS; i++) { 312 if ( HSP_IS_PORT_HT_MODE(i) ) 313 { 314 ht_map |= (1 << i); 315 } 316 } 317 318 /* HSP: Allocate RX and TX buffers. */ 319 for (i = 0; i < BCM1480_HT_NUM_PORTS; i++) { 320 if (HSP_PORT_MODE_HT(ht_map, i)) 321 hsp_ht_ram_alloc(i); 322 } 323 324 /* HSP: Program the flow control registers. */ 325 for (i = 0; i < BCM1480_HT_NUM_PORTS; i++) { 326 if (HSP_PORT_MODE_HT(ht_map, i)) 327 hsp_ht_flow_alloc(i); 328 } 329 330 return ht_map; 331} 332 333/** 334 @fn void hsp_pm_ram_n_flow_alloc(uint32_t port_idx, uint32_t num_active ); 335*/ 336void hsp_pm_ram_n_flow_alloc(uint32_t port, uint32_t num_active ) 337{ 338 int total_tx_ram,total_rx_ram; 339 int per_tx_channel,per_rx_channel; 340 int i; 341 int cur_floor; 342 uint64_t ramalloc[8]; 343 uint64_t phitcnt[4]; 344 uint64_t watermark[8]; 345 int almostfull,almostempty; 346 347 /* XXX this relies on a hard-coded agreement between the HT init code 348 (same as the PCI init) and the code here. We know that HT init 349 has put all the ccNUMA and PoHT at 0x300 and above for RX and 350 0xc0 and above for TX. */ 351 352 total_rx_ram = 1024 - 256; /* number of 16-byte blocks */ 353 total_tx_ram = 256 - 64; /* number of 16-byte blocks */ 354 355 per_tx_channel = total_tx_ram / num_active; 356 per_rx_channel = total_rx_ram / num_active; 357 358 /* 359 * Set the "almost full" watermark to 512 bytes (32 blocks) or 1/2 the 360 * per channel allocation, whichever is smaller. Set the "almost empty" 361 * watermark to 1/4 the allocation. 362 */ 363 364 almostfull = per_rx_channel / 2; 365 if (almostfull > 32) almostfull = per_rx_channel - 32; 366 367 almostempty = per_rx_channel / 4; 368 369 /* This shouldn't happen, but we want to prevent the chip from going insane. */ 370 if (almostempty > almostfull) almostempty = almostfull / 2; 371 372 373 printf("** TX: alloc=%d RX: alloc=%d full=%d empty=%d\n",per_tx_channel, 374 per_rx_channel,almostfull,almostempty); 375 376 /* 377 * Do RX side 378 */ 379 380 cur_floor = 0; 381 memset(ramalloc,0,sizeof(ramalloc)); 382 memset(phitcnt,0,sizeof(phitcnt)); 383 memset(watermark,0,sizeof(watermark)); 384 385 for (i = 0; i < num_active; i++) { 386 switch (i & 1) { 387 case 0: 388 ramalloc[i/2] |= V_BCM1480_HSP_RX_RAMCEILING_0(cur_floor+per_rx_channel-1)| 389 V_BCM1480_HSP_RX_RAMFLOOR_0(cur_floor); 390 break; 391 case 1: 392 ramalloc[i/2] |= V_BCM1480_HSP_RX_RAMCEILING_1(cur_floor+per_rx_channel-1)| 393 V_BCM1480_HSP_RX_RAMFLOOR_1(cur_floor); 394 break; 395 } 396 397 switch (i & 1) { 398 case 0: 399 watermark[i/2] |= V_BCM1480_HSP_RX_ALMOSTEMPTY_EVEN(almostempty) | 400 V_BCM1480_HSP_RX_ALMOSTFULL_EVEN(almostfull); 401 break; 402 case 1: 403 watermark[i/2] |= V_BCM1480_HSP_RX_ALMOSTEMPTY_ODD(almostempty) | 404 V_BCM1480_HSP_RX_ALMOSTFULL_ODD(almostfull); 405 break; 406 } 407 408 switch (i & 3) { 409 case 0: 410 phitcnt[i/4] |= V_BCM1480_HSP_RX_PHITCNT_0(per_rx_channel/4); 411 break; 412 case 1: 413 phitcnt[i/4] |= V_BCM1480_HSP_RX_PHITCNT_1(per_rx_channel/4); 414 break; 415 case 2: 416 phitcnt[i/4] |= V_BCM1480_HSP_RX_PHITCNT_2(per_rx_channel/4); 417 break; 418 case 3: 419 phitcnt[i/4] |= V_BCM1480_HSP_RX_PHITCNT_3(per_rx_channel/4); 420 break; 421 } 422 423 cur_floor += per_rx_channel; 424 425 } 426 427 /* 428 * Now transfer these calculations into the RX registers. 429 */ 430 431 for (i = 0; i < 8; i++) { 432 WRITECSR(A_BCM1480_HSP_REGISTER(port,R_BCM1480_HSP_RX_PKT_RAMALLOC(i)),ramalloc[i]); 433 } 434 435 for (i = 0; i < 8; i++) { 436 WRITECSR(A_BCM1480_HSP_REGISTER(port,R_BCM1480_HSP_RX_SPI_WATERMARK(i)),watermark[i]); 437 } 438 439 for (i = 0; i < 4; i++) { 440 WRITECSR(A_BCM1480_HSP_REGISTER(port,R_BCM1480_HSP_TX_PKT_RXPHITCNT(i)),phitcnt[i]); 441 } 442 443 /* 444 * Now do the TX side. 445 */ 446 447 448 cur_floor = 0; 449 memset(ramalloc,0,sizeof(ramalloc)); 450 memset(phitcnt,0,sizeof(phitcnt)); 451 452 for (i = 0; i < num_active; i++) { 453 if (i & 1) { 454 ramalloc[i/2] |= V_BCM1480_HSP_TX_RAMCEILING_1(cur_floor+per_tx_channel-1)| 455 V_BCM1480_HSP_TX_RAMFLOOR_1(cur_floor); 456 } 457 else { 458 ramalloc[i/2] |= V_BCM1480_HSP_TX_RAMCEILING_0(cur_floor+per_tx_channel-1)| 459 V_BCM1480_HSP_TX_RAMFLOOR_0(cur_floor); 460 } 461 462 switch (i & 3) { 463 case 0: 464 phitcnt[i/4] |= V_BCM1480_HSP_TX_PHITCNT_0(per_tx_channel); 465 break; 466 case 1: 467 phitcnt[i/4] |= V_BCM1480_HSP_TX_PHITCNT_1(per_tx_channel); 468 break; 469 case 2: 470 phitcnt[i/4] |= V_BCM1480_HSP_TX_PHITCNT_2(per_tx_channel); 471 break; 472 case 3: 473 phitcnt[i/4] |= V_BCM1480_HSP_TX_PHITCNT_3(per_tx_channel); 474 break; 475 } 476 477 cur_floor += per_tx_channel; 478 479 } 480 481 482 /* 483 * Now transfer these calculations into the TX registers. 484 */ 485 486 for (i = 0; i < 8; i++) { 487 WRITECSR(A_BCM1480_HSP_REGISTER(port,R_BCM1480_HSP_TX_PKT_RAMALLOC(i)),ramalloc[i]); 488 } 489 490 for (i = 0; i < 4; i++) { 491 WRITECSR(A_BCM1480_HSP_REGISTER(port,R_BCM1480_HSP_TX_PKT_TXPHITCNT(i)),phitcnt[i]); 492 } 493 494} 495 496 497/** 498 @fn void hsp_ht_port_link_reset( uint32_t port ); 499*/ 500void hsp_ht_port_link_reset( uint32_t port ) 501{ 502 volatile pcireg_t cmd, ctrl; 503 504 if (port > BCM1480_HT_NUM_PORTS) 505 { 506 printf("ht_port_link_reset: Invalid port %d parameter\n"); 507 goto ERROR_EXIT; 508 } 509 510 /* 511 * Now issue a soft reset to force the link to renegotiate the new speed and reestablish 512 * credit 513 */ 514 ctrl = pci_conf_read32(BCM1480_EXTx_BRIDGE(port), R_LDT_BRCMD); 515 ctrl |= LDT_COMMAND_WARM_RESET; 516 pci_conf_write32(BCM1480_EXTx_BRIDGE(port), R_LDT_BRCMD, ctrl); 517 cmd = pci_conf_read32(BCM1480_EXTx_BRIDGE(port), PPB_BRCTL_INTERRUPT_REG); 518 cmd |= M_PPB_BRCTL_SECBUSRESET; 519 pci_conf_write32(BCM1480_EXTx_BRIDGE(port), PPB_BRCTL_INTERRUPT_REG, cmd); 520 521 cfe_usleep(1000); 522 523 cmd = pci_conf_read32(BCM1480_EXTx_BRIDGE(port), PPB_BRCTL_INTERRUPT_REG); 524 cmd &= ~M_PPB_BRCTL_SECBUSRESET; 525 pci_conf_write32(BCM1480_EXTx_BRIDGE(port), PPB_BRCTL_INTERRUPT_REG, cmd); 526 527ERROR_EXIT: 528 529 return; 530} 531 532 533/** 534 @fn void hsp_spi4_init_port(uint32_t port, 535 uint32_t mhz, 536 uint32_t active_channels, 537 uint32_t rstat); 538*/ 539void hsp_spi4_init_port(uint32_t port, 540 uint32_t mhz, 541 uint32_t active_channels, 542 uint32_t rstat) 543{ 544 uint64_t value; 545 int spi4_pllmult; 546 uint64_t cpu_mhz; 547 uint64_t sw_mhz; 548 uint64_t spi4_mhz = mhz; 549 550 cpu_mhz = G_BCM1480_SYS_PLL_DIV(READCSR(A_SCD_SYSTEM_CFG)) * (REFCLK/2); 551 sw_mhz = cpu_mhz * 2 / G_BCM1480_SYS_SW_DIV(READCSR(A_SCD_SYSTEM_CFG)); 552 553 spi4_pllmult = spi4_mhz / (REFCLK/2); 554 555 /* enable the calendar */ 556 557 uint64_t v0, v1; 558 559 // do all 16 if we're doing more than one (could optimize 560 // further if we really need to, for 2 VCs for example) 561 if (active_channels > 1) { 562 v0 = 0x0706050403020100LL; 563 v1 = 0x0F0E0D0C0B0A0908LL; 564 } 565 else { 566 v0 = 0; // VC 0 for all 16 calendar slots 567 v1 = 0; 568 } 569 printf("writing calendar 0x%x 0x%x\n", v0, v1); 570 // most general calendar--each VC gets a slot 571 WRITECSR(A_BCM1480_HSP_REGISTER(port,R_BCM1480_HSP_TX_SPI4_CALENDAR_0),v0); 572 WRITECSR(A_BCM1480_HSP_REGISTER(port,R_BCM1480_HSP_TX_SPI4_CALENDAR_1),v1); 573 574 WRITECSR(A_BCM1480_HSP_REGISTER(port,R_BCM1480_HSP_RX_SPI4_CALENDAR_0),v0); 575 WRITECSR(A_BCM1480_HSP_REGISTER(port,R_BCM1480_HSP_RX_SPI4_CALENDAR_1),v1); 576 577 value = V_BCM1480_HSP_RX_CALENDAR_LEN(CALENDAR_LEN) | 578 V_BCM1480_HSP_RX_CALENDAR_M(CALENDAR_M) | 579 V_BCM1480_HSP_RX_ALPHA(4000); 580 581 WRITECSR(A_BCM1480_HSP_REGISTER(port,R_BCM1480_HSP_RX_SPI4_CFG_1),value); 582 583 value = V_BCM1480_HSP_TX_MAXBURST1(8) | 584 V_BCM1480_HSP_TX_MAXBURST2(4) | 585 V_BCM1480_HSP_TX_CALENDAR_LEN(CALENDAR_LEN) | 586 V_BCM1480_HSP_TX_CALENDAR_M(CALENDAR_M) | 587 V_BCM1480_HSP_TX_ALPHA(4000) | 588 V_BCM1480_HSP_TX_ACTIVE_CHANNELS(active_channels); 589 590 WRITECSR(A_BCM1480_HSP_REGISTER(port,R_BCM1480_HSP_TX_SPI4_CFG_1),value); 591 592 /* Enable status register */ 593 WRITECSR(A_BCM1480_HSP_REGISTER(port,R_BCM1480_HSP_TX_SPI4_PORT_INT_EN), 594 (M_BCM1480_HSP_TX_INT_TSTATTIMEOUT | 595 M_BCM1480_HSP_TX_INT_DIP2RXERR | 596 M_BCM1480_HSP_TX_INT_SPI4RESET)); 597 598 /* Watch for all RX errors */ 599 WRITECSR(A_BCM1480_HSP_REGISTER(port,R_BCM1480_HSP_RX_SPI4_PORT_INT_EN), 600 (M_BCM1480_HSP_RX_INT_PERVCERR | 601 M_BCM1480_HSP_RX_INT_EOPABORT | 602 M_BCM1480_HSP_RX_INT_SPI4PROTOERR | 603 M_BCM1480_HSP_RX_INT_ESTOREOVERFLOW | 604 M_BCM1480_HSP_RX_INT_ALPHATRAINERR | 605 M_BCM1480_HSP_RX_INT_DIP4ERROR | 606 M_BCM1480_HSP_RX_INT_HRERROR | 607 M_BCM1480_HSP_RX_INT_INTOVERFLOW)); 608 609 610 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 611 612 /* 613 * Do the RX SPI4 config register. Be sure to enable divide-by-4 mode 614 * if running < 200Mhz 615 */ 616 617 value = READCSR(A_BCM1480_HSP_REGISTER(port,R_BCM1480_HSP_RX_SPI4_CFG_0)); 618 619 value &= ~(M_BCM1480_HSP_RX_PLL_MULTIPLIER | M_BCM1480_HSP_RX_PLL_DIV_4); 620 621 if (spi4_mhz < 200) { 622 value |= V_BCM1480_HSP_RX_PLL_MULTIPLIER(spi4_pllmult*4) | M_BCM1480_HSP_RX_PLL_DIV_4; 623 } 624 else { 625 value |= V_BCM1480_HSP_RX_PLL_MULTIPLIER(spi4_pllmult); 626 } 627 628 value &= ~_SB_MAKEMASK1(1); /* Clear reserved bit */ 629 630 if (rstat) { 631 /* For loopbackEnable either RX or TX rstat polarity, not both */ 632 value |= M_BCM1480_HSP_RSTAT_POLARITY; 633 printf("HSP[%d] Setting M_BCM1480_HSP_RSTAT_POLARITY for " 634 "loopback\n", port); 635 } 636 637 WRITECSR(A_BCM1480_HSP_REGISTER(port,R_BCM1480_HSP_RX_SPI4_CFG_0),value); 638 639 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 640 641 /* 642 * TX SPI4 Training Format Register 643 */ 644 645 /* The following register values makes TX to send some data out!! Please don't change!! */ 646 value = READCSR(A_BCM1480_HSP_REGISTER(port,R_BCM1480_HSP_TX_SPI4_TRAINING_FMT)); 647 value &= ~M_BCM1480_HSP_TX_TXPREFBURSTSZ; 648 value |= V_BCM1480_HSP_TX_TXPREFBURSTSZ(2); 649 value &= ~M_BCM1480_HSP_TX_TXMAXBURSTSZ; 650 value |= V_BCM1480_HSP_TX_TXMAXBURSTSZ(5); 651 WRITECSR(A_BCM1480_HSP_REGISTER(port,R_BCM1480_HSP_TX_SPI4_TRAINING_FMT),value); 652 value = READCSR(A_BCM1480_HSP_REGISTER(port,R_BCM1480_HSP_TX_SPI4_TRAINING_FMT)); 653 654 655 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 656 657 /* 658 * Fix up the calibration registers. For TX, turn off the "STARTCAL2" 659 * bit. It shouldn't be set, but it is. For RX, disable "No Calibration" 660 * mode to allow the RX side to do its calibrations. 661 */ 662 663 value = READCSR(A_BCM1480_HSP_REGISTER(port,R_BCM1480_HSP_TX_CALIBRATION)); 664 value &= ~M_BCM1480_HSP_CAL_STARTCAL2; 665 WRITECSR(A_BCM1480_HSP_REGISTER(port,R_BCM1480_HSP_TX_CALIBRATION),value); 666 667 value = READCSR(A_BCM1480_HSP_REGISTER(port,R_BCM1480_HSP_RX_CALIBRATION)); 668 value &= ~M_BCM1480_HSP_CAL_NO_CALIB; 669 WRITECSR(A_BCM1480_HSP_REGISTER(port,R_BCM1480_HSP_RX_CALIBRATION),value); 670 671 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 672 673 /* 674 * Do the SPI4 TX Config register 0. This register contains PLL settings 675 * and error count tolerances. 676 */ 677 678 value = READCSR(A_BCM1480_HSP_REGISTER(port,R_BCM1480_HSP_TX_SPI4_CFG_0)); 679 value &= ~M_BCM1480_HSP_TX_RST_STATCNT; 680 value |= V_BCM1480_HSP_TX_RST_STATCNT(0); 681 682 /* 683 * For the PLL, make sure the ratios are all sane. If the spi4 clock 684 * is less than 200MHz, be sure to turn on the "divide-by-4" mode 685 * and run the PLL 4x faster. 686 */ 687 688 value &= ~(M_BCM1480_HSP_TX_PLL_MULTIPLIER | M_BCM1480_HSP_TX_TX_PLL_DIV_4); 689 690 if (spi4_mhz < 200) { 691 value |= V_BCM1480_HSP_TX_PLL_MULTIPLIER(spi4_pllmult*4) | M_BCM1480_HSP_TX_TX_PLL_DIV_4; 692 } 693 else { 694 value |= V_BCM1480_HSP_TX_PLL_MULTIPLIER(spi4_pllmult); 695 } 696 697 /* 698 * TSTATCLK is 1/4 the SPI clock. If (TSTATCLK/4)/SWCLK is < 1/4, turn 699 * on TSTAT slow mode. 700 */ 701 if ((spi4_mhz / sw_mhz) < 4) { 702 value |= M_BCM1480_HSP_TX_TSTAT_SLOW_MODE; 703 } 704 705 /* 'n' DIP-2 Errors causes TX to go to Link Training */ 706 value &= ~M_BCM1480_HSP_TX_DIP2_ERRLIMIT; 707 value |= V_BCM1480_HSP_TX_DIP2_ERRLIMIT(1); 708// value |= M_BCM1480_HSP_TX_TSTAT_POLARITY; 709 710 711 WRITECSR(A_BCM1480_HSP_REGISTER(port,R_BCM1480_HSP_TX_SPI4_CFG_0),value); 712 713 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 714 715 cfe_usleep(10000); 716 717 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 718 719 /* 720 * Bring ports out of reset. 721 */ 722 723 value = READCSR(A_BCM1480_HSP_REGISTER(port,R_BCM1480_HSP_TX_SPI4_CFG_0)); 724 value &= ~M_BCM1480_HSP_TX_PORT_RESET; 725 WRITECSR(A_BCM1480_HSP_REGISTER(port,R_BCM1480_HSP_TX_SPI4_CFG_0),value); 726 727 /* Enable RX Port */ 728 value = READCSR(A_BCM1480_HSP_REGISTER(port,R_BCM1480_HSP_RX_SPI4_CFG_0)); 729 value &= ~M_BCM1480_HSP_RX_PORT_RESET; 730 WRITECSR(A_BCM1480_HSP_REGISTER(port,R_BCM1480_HSP_RX_SPI4_CFG_0),value); 731} 732 733 734/** 735 @fn uint32_t hsp_ht_reset_errors(uint32_t port); 736*/ 737uint32_t hsp_ht_reset_errors(uint32_t port) 738{ 739 pcireg_t csr; 740 741 /* 742 * Clear standard PCI errors on primary status register 743 */ 744 csr = pci_conf_read32(BCM1480_EXTx_BRIDGE(port), PCI_COMMAND_STATUS_REG); 745 csr |= PCI_STATUS_PARITY_ERROR | PCI_STATUS_SYSTEM_ERROR | 746 PCI_STATUS_MASTER_ABORT | PCI_STATUS_MASTER_TARGET_ABORT | 747 PCI_STATUS_TARGET_TARGET_ABORT | PCI_STATUS_PARITY_DETECT; 748 pci_conf_write32(BCM1480_EXTx_BRIDGE(port), PCI_COMMAND_STATUS_REG, csr); 749 750 /* 751 * Clear standard PCI errors on secondary (bridge) status register 752 */ 753 csr = pci_conf_read32(BCM1480_EXTx_BRIDGE(port), PPB_IO_STATUS_REG); 754 csr |= PCI_STATUS_PARITY_ERROR | PCI_STATUS_SYSTEM_ERROR | 755 PCI_STATUS_MASTER_ABORT | PCI_STATUS_MASTER_TARGET_ABORT | 756 PCI_STATUS_TARGET_TARGET_ABORT | PCI_STATUS_PARITY_DETECT; 757 pci_conf_write32(BCM1480_EXTx_BRIDGE(port), PPB_IO_STATUS_REG, csr); 758 759 760 /* 761 * Clear Link Fail and CRC status bits in bridge link status register 762 */ 763 csr = pci_conf_read32(BCM1480_EXTx_BRIDGE(port), R_BCM1480_HTB_LINKCTRL); 764 csr |= M_BCM1480_HTB_LINKCTRL_LINKFAIL | M_BCM1480_HTB_LINKCTRL_CRCERR; 765 pci_conf_write32(BCM1480_EXTx_BRIDGE(port), R_BCM1480_HTB_LINKCTRL, csr); 766 767 768 /* 769 * Clear Protocol, Overflow, and End of Chain status bits 770 */ 771 csr = pci_conf_read32(BCM1480_EXTx_BRIDGE(port), R_BCM1480_HTB_LINKFREQERR); 772 csr |= M_BCM1480_HTB_LINKFQERR_PROTERR | M_BCM1480_HTB_LINKFQERR_OVFLERR | 773 M_BCM1480_HTB_LINKFQERR_EOCERR; 774 pci_conf_write32(BCM1480_EXTx_BRIDGE(port), R_BCM1480_HTB_LINKFREQERR, csr); 775 776 777 /* 778 * Clear Chain Fail(Sync flood) and Respond error status bits 779 */ 780 csr = pci_conf_read32(BCM1480_EXTx_BRIDGE(port), R_BCM1480_HTB_ERRHNDL); 781 csr |= M_BCM1480_HTB_ERRHNDL_CHNFAIL | M_BCM1480_HTB_ERRHNDL_RSPERR; 782 pci_conf_write32(BCM1480_EXTx_BRIDGE(port), R_BCM1480_HTB_ERRHNDL, csr); 783 784 return (0); 785} 786 787 788/** 789 uint32_t hsp_ht_enable_sync_flood_on_errors(uint32_t port, uint32_t enable); 790*/ 791uint32_t hsp_ht_enable_sync_flood_on_errors(uint32_t port, uint32_t enable) 792{ 793 pcireg_t csr; 794 795 /* 796 * Enable / Disable Sync Flood on CRC 797 */ 798 csr = pci_conf_read32(BCM1480_EXTx_BRIDGE(port), R_BCM1480_HTB_LINKCTRL); 799 if (enable) 800 { 801 csr |= M_BCM1480_HTB_LINKCTRL_CRCFLEN; 802 } 803 else 804 { 805 csr &= ~M_BCM1480_HTB_LINKCTRL_CRCFLEN; 806 } 807 pci_conf_write32(BCM1480_EXTx_BRIDGE(port), R_BCM1480_HTB_LINKCTRL, csr); 808 809 /* 810 * Enable / Disable Sync Flood on Protocol and Overflow errors 811 */ 812 csr = pci_conf_read32(BCM1480_EXTx_BRIDGE(port), R_BCM1480_HTB_ERRHNDL); 813 if (enable) 814 { 815 csr |= M_BCM1480_HTB_ERRHNDL_PROFLEN | M_BCM1480_HTB_LINKFQERR_OVFLERR ; 816 } 817 else 818 { 819 csr &= ~(M_BCM1480_HTB_ERRHNDL_PROFLEN | M_BCM1480_HTB_LINKFQERR_OVFLERR); 820 } 821 pci_conf_write32(BCM1480_EXTx_BRIDGE(port), R_BCM1480_HTB_ERRHNDL, csr); 822 823 return (0); 824 825} 826 827 828/** 829 uint32_t hsp_ht_check_for_errors(uint32_t port); 830*/ 831uint32_t hsp_ht_check_for_errors(uint32_t port) 832{ 833 pcireg_t reg; 834 uint32_t b_error = 0; 835 836 /* 837 * Check standard PCI errors on primary status register 838 */ 839 reg = pci_conf_read32(BCM1480_EXTx_BRIDGE(port), PCI_COMMAND_STATUS_REG); 840 b_error |= ( reg & (PCI_STATUS_PARITY_ERROR | PCI_STATUS_SYSTEM_ERROR | 841 PCI_STATUS_MASTER_ABORT | PCI_STATUS_MASTER_TARGET_ABORT | 842 PCI_STATUS_TARGET_TARGET_ABORT | PCI_STATUS_PARITY_DETECT)) ? 1 : 0; 843 /* 844 * Check standard PCI errors on secondary (bridge) status register 845 */ 846 reg = pci_conf_read32(BCM1480_EXTx_BRIDGE(port), PPB_IO_STATUS_REG); 847 b_error |= ( reg & (PCI_STATUS_PARITY_ERROR | PCI_STATUS_SYSTEM_ERROR | 848 PCI_STATUS_MASTER_ABORT | PCI_STATUS_MASTER_TARGET_ABORT | 849 PCI_STATUS_TARGET_TARGET_ABORT | PCI_STATUS_PARITY_DETECT)) ? 1 : 0; 850 851 /* 852 * Check Link Fail and CRC status bits in bridge link status register 853 */ 854 reg = pci_conf_read32(BCM1480_EXTx_BRIDGE(port), R_BCM1480_HTB_LINKCTRL); 855 b_error |= ( reg & ( M_BCM1480_HTB_LINKCTRL_LINKFAIL | M_BCM1480_HTB_LINKCTRL_CRCERR)) ? 1 : 0; 856 857 /* 858 * Check Protocol, Overflow, and End of Chain status bits 859 */ 860 reg = pci_conf_read32(BCM1480_EXTx_BRIDGE(port), R_BCM1480_HTB_LINKFREQERR); 861 b_error |= ( reg & ( M_BCM1480_HTB_LINKFQERR_PROTERR | M_BCM1480_HTB_LINKFQERR_OVFLERR | 862 M_BCM1480_HTB_LINKFQERR_EOCERR)) ? 1 : 0; 863 864 /* 865 * Check Chain Fail(Sync flood) and Respond error status bits 866 */ 867 reg = pci_conf_read32(BCM1480_EXTx_BRIDGE(port), R_BCM1480_HTB_ERRHNDL); 868 b_error |= ( reg & ( M_BCM1480_HTB_ERRHNDL_CHNFAIL | M_BCM1480_HTB_ERRHNDL_RSPERR )) ? 1 : 0; 869 870 return (b_error); 871} 872 873 874 875/** 876 uint32_t hsp_spi4_reset_errors(uint32_t port) 877*/ 878uint32_t hsp_spi4_reset_errors(uint32_t port) 879{ 880 881 /* Clear TX irq status register */ 882 WRITECSR(A_BCM1480_HSP_REGISTER(port,R_BCM1480_HSP_TX_SPI4_PORT_INT_STATUS), 883 (M_BCM1480_HSP_TX_INT_TSTATTIMEOUT | 884 M_BCM1480_HSP_TX_INT_DIP2RXERR | 885 M_BCM1480_HSP_TX_INT_SPI4RESET)); 886 887 /* Clear RX irq for all RX errors */ 888 WRITECSR(A_BCM1480_HSP_REGISTER(port,R_BCM1480_HSP_RX_SPI4_PORT_INT_STATUS), 889 (M_BCM1480_HSP_RX_INT_PERVCERR | 890 M_BCM1480_HSP_RX_INT_EOPABORT | 891 M_BCM1480_HSP_RX_INT_SPI4PROTOERR | 892 M_BCM1480_HSP_RX_INT_ESTOREOVERFLOW | 893 M_BCM1480_HSP_RX_INT_ALPHATRAINERR | 894 M_BCM1480_HSP_RX_INT_DIP4ERROR | 895 M_BCM1480_HSP_RX_INT_HRERROR | 896 M_BCM1480_HSP_RX_INT_INTOVERFLOW)); 897 898 return(0); 899} 900 901 902 903 904 905/** 906 uint32_t hsp_spi4_check_for_errors(uint32_t port) 907*/ 908uint32_t hsp_spi4_check_for_errors(uint32_t port) 909{ 910 uint32_t b_error = 0; 911 uint64_t csr; 912 913 914 /* Check TX irq status register */ 915 csr = READCSR(A_BCM1480_HSP_REGISTER(port,R_BCM1480_HSP_TX_SPI4_PORT_INT_STATUS) ); 916 917 b_error |= (csr & (M_BCM1480_HSP_TX_INT_TSTATTIMEOUT | 918 M_BCM1480_HSP_TX_INT_DIP2RXERR | 919 M_BCM1480_HSP_TX_INT_SPI4RESET)) ? 1 : 0; 920 921 /* Check RX irq for all RX errors */ 922 csr = READCSR(A_BCM1480_HSP_REGISTER(port,R_BCM1480_HSP_RX_SPI4_PORT_INT_STATUS) ); 923 924 b_error |= (csr & (M_BCM1480_HSP_RX_INT_PERVCERR | 925 M_BCM1480_HSP_RX_INT_EOPABORT | 926 M_BCM1480_HSP_RX_INT_SPI4PROTOERR | 927 M_BCM1480_HSP_RX_INT_ESTOREOVERFLOW | 928 M_BCM1480_HSP_RX_INT_ALPHATRAINERR | 929 M_BCM1480_HSP_RX_INT_DIP4ERROR | 930 M_BCM1480_HSP_RX_INT_HRERROR | 931 M_BCM1480_HSP_RX_INT_INTOVERFLOW)) ? 1 : 0; 932 933 934 return (b_error); 935} 936 937 938 939