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