1/* bnx2x_init.h: Qlogic Everest network driver.
2 *               Structures and macroes needed during the initialization.
3 *
4 * Copyright (c) 2007-2013 Broadcom Corporation
5 * Copyright (c) 2014 QLogic Corporation
6 All rights reserved
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation.
11 *
12 * Maintained by: Ariel Elior <ariel.elior@qlogic.com>
13 * Written by: Eliezer Tamir
14 * Modified by: Vladislav Zolotarov
15 */
16
17#ifndef BNX2X_INIT_H
18#define BNX2X_INIT_H
19
20/* Init operation types and structures */
21enum {
22	OP_RD = 0x1,	/* read a single register */
23	OP_WR,		/* write a single register */
24	OP_SW,		/* copy a string to the device */
25	OP_ZR,		/* clear memory */
26	OP_ZP,		/* unzip then copy with DMAE */
27	OP_WR_64,	/* write 64 bit pattern */
28	OP_WB,		/* copy a string using DMAE */
29	OP_WB_ZR,	/* Clear a string using DMAE or indirect-wr */
30	/* Skip the following ops if all of the init modes don't match */
31	OP_IF_MODE_OR,
32	/* Skip the following ops if any of the init modes don't match */
33	OP_IF_MODE_AND,
34	OP_MAX
35};
36
37enum {
38	STAGE_START,
39	STAGE_END,
40};
41
42/* Returns the index of start or end of a specific block stage in ops array*/
43#define BLOCK_OPS_IDX(block, stage, end) \
44	(2*(((block)*NUM_OF_INIT_PHASES) + (stage)) + (end))
45
46
47/* structs for the various opcodes */
48struct raw_op {
49	u32 op:8;
50	u32 offset:24;
51	u32 raw_data;
52};
53
54struct op_read {
55	u32 op:8;
56	u32 offset:24;
57	u32 val;
58};
59
60struct op_write {
61	u32 op:8;
62	u32 offset:24;
63	u32 val;
64};
65
66struct op_arr_write {
67	u32 op:8;
68	u32 offset:24;
69#ifdef __BIG_ENDIAN
70	u16 data_len;
71	u16 data_off;
72#else /* __LITTLE_ENDIAN */
73	u16 data_off;
74	u16 data_len;
75#endif
76};
77
78struct op_zero {
79	u32 op:8;
80	u32 offset:24;
81	u32 len;
82};
83
84struct op_if_mode {
85	u32 op:8;
86	u32 cmd_offset:24;
87	u32 mode_bit_map;
88};
89
90
91union init_op {
92	struct op_read		read;
93	struct op_write		write;
94	struct op_arr_write	arr_wr;
95	struct op_zero		zero;
96	struct raw_op		raw;
97	struct op_if_mode	if_mode;
98};
99
100
101/* Init Phases */
102enum {
103	PHASE_COMMON,
104	PHASE_PORT0,
105	PHASE_PORT1,
106	PHASE_PF0,
107	PHASE_PF1,
108	PHASE_PF2,
109	PHASE_PF3,
110	PHASE_PF4,
111	PHASE_PF5,
112	PHASE_PF6,
113	PHASE_PF7,
114	NUM_OF_INIT_PHASES
115};
116
117/* Init Modes */
118enum {
119	MODE_ASIC                      = 0x00000001,
120	MODE_FPGA                      = 0x00000002,
121	MODE_EMUL                      = 0x00000004,
122	MODE_E2                        = 0x00000008,
123	MODE_E3                        = 0x00000010,
124	MODE_PORT2                     = 0x00000020,
125	MODE_PORT4                     = 0x00000040,
126	MODE_SF                        = 0x00000080,
127	MODE_MF                        = 0x00000100,
128	MODE_MF_SD                     = 0x00000200,
129	MODE_MF_SI                     = 0x00000400,
130	MODE_MF_AFEX                   = 0x00000800,
131	MODE_E3_A0                     = 0x00001000,
132	MODE_E3_B0                     = 0x00002000,
133	MODE_COS3                      = 0x00004000,
134	MODE_COS6                      = 0x00008000,
135	MODE_LITTLE_ENDIAN             = 0x00010000,
136	MODE_BIG_ENDIAN                = 0x00020000,
137};
138
139/* Init Blocks */
140enum {
141	BLOCK_ATC,
142	BLOCK_BRB1,
143	BLOCK_CCM,
144	BLOCK_CDU,
145	BLOCK_CFC,
146	BLOCK_CSDM,
147	BLOCK_CSEM,
148	BLOCK_DBG,
149	BLOCK_DMAE,
150	BLOCK_DORQ,
151	BLOCK_HC,
152	BLOCK_IGU,
153	BLOCK_MISC,
154	BLOCK_NIG,
155	BLOCK_PBF,
156	BLOCK_PGLUE_B,
157	BLOCK_PRS,
158	BLOCK_PXP2,
159	BLOCK_PXP,
160	BLOCK_QM,
161	BLOCK_SRC,
162	BLOCK_TCM,
163	BLOCK_TM,
164	BLOCK_TSDM,
165	BLOCK_TSEM,
166	BLOCK_UCM,
167	BLOCK_UPB,
168	BLOCK_USDM,
169	BLOCK_USEM,
170	BLOCK_XCM,
171	BLOCK_XPB,
172	BLOCK_XSDM,
173	BLOCK_XSEM,
174	BLOCK_MISC_AEU,
175	NUM_OF_INIT_BLOCKS
176};
177
178/* QM queue numbers */
179#define BNX2X_ETH_Q		0
180#define BNX2X_TOE_Q		3
181#define BNX2X_TOE_ACK_Q		6
182#define BNX2X_ISCSI_Q		9
183#define BNX2X_ISCSI_ACK_Q	11
184#define BNX2X_FCOE_Q		10
185
186/* Vnics per mode */
187#define BNX2X_PORT2_MODE_NUM_VNICS 4
188#define BNX2X_PORT4_MODE_NUM_VNICS 2
189
190/* COS offset for port1 in E3 B0 4port mode */
191#define BNX2X_E3B0_PORT1_COS_OFFSET 3
192
193/* QM Register addresses */
194#define BNX2X_Q_VOQ_REG_ADDR(pf_q_num)\
195	(QM_REG_QVOQIDX_0 + 4 * (pf_q_num))
196#define BNX2X_VOQ_Q_REG_ADDR(cos, pf_q_num)\
197	(QM_REG_VOQQMASK_0_LSB + 4 * ((cos) * 2 + ((pf_q_num) >> 5)))
198#define BNX2X_Q_CMDQ_REG_ADDR(pf_q_num)\
199	(QM_REG_BYTECRDCMDQ_0 + 4 * ((pf_q_num) >> 4))
200
201/* extracts the QM queue number for the specified port and vnic */
202#define BNX2X_PF_Q_NUM(q_num, port, vnic)\
203	((((port) << 1) | (vnic)) * 16 + (q_num))
204
205
206/* Maps the specified queue to the specified COS */
207static inline void bnx2x_map_q_cos(struct bnx2x *bp, u32 q_num, u32 new_cos)
208{
209	/* find current COS mapping */
210	u32 curr_cos = REG_RD(bp, QM_REG_QVOQIDX_0 + q_num * 4);
211
212	/* check if queue->COS mapping has changed */
213	if (curr_cos != new_cos) {
214		u32 num_vnics = BNX2X_PORT2_MODE_NUM_VNICS;
215		u32 reg_addr, reg_bit_map, vnic;
216
217		/* update parameters for 4port mode */
218		if (INIT_MODE_FLAGS(bp) & MODE_PORT4) {
219			num_vnics = BNX2X_PORT4_MODE_NUM_VNICS;
220			if (BP_PORT(bp)) {
221				curr_cos += BNX2X_E3B0_PORT1_COS_OFFSET;
222				new_cos += BNX2X_E3B0_PORT1_COS_OFFSET;
223			}
224		}
225
226		/* change queue mapping for each VNIC */
227		for (vnic = 0; vnic < num_vnics; vnic++) {
228			u32 pf_q_num =
229				BNX2X_PF_Q_NUM(q_num, BP_PORT(bp), vnic);
230			u32 q_bit_map = 1 << (pf_q_num & 0x1f);
231
232			/* overwrite queue->VOQ mapping */
233			REG_WR(bp, BNX2X_Q_VOQ_REG_ADDR(pf_q_num), new_cos);
234
235			/* clear queue bit from current COS bit map */
236			reg_addr = BNX2X_VOQ_Q_REG_ADDR(curr_cos, pf_q_num);
237			reg_bit_map = REG_RD(bp, reg_addr);
238			REG_WR(bp, reg_addr, reg_bit_map & (~q_bit_map));
239
240			/* set queue bit in new COS bit map */
241			reg_addr = BNX2X_VOQ_Q_REG_ADDR(new_cos, pf_q_num);
242			reg_bit_map = REG_RD(bp, reg_addr);
243			REG_WR(bp, reg_addr, reg_bit_map | q_bit_map);
244
245			/* set/clear queue bit in command-queue bit map
246			 * (E2/E3A0 only, valid COS values are 0/1)
247			 */
248			if (!(INIT_MODE_FLAGS(bp) & MODE_E3_B0)) {
249				reg_addr = BNX2X_Q_CMDQ_REG_ADDR(pf_q_num);
250				reg_bit_map = REG_RD(bp, reg_addr);
251				q_bit_map = 1 << (2 * (pf_q_num & 0xf));
252				reg_bit_map = new_cos ?
253					      (reg_bit_map | q_bit_map) :
254					      (reg_bit_map & (~q_bit_map));
255				REG_WR(bp, reg_addr, reg_bit_map);
256			}
257		}
258	}
259}
260
261/* Configures the QM according to the specified per-traffic-type COSes */
262static inline void bnx2x_dcb_config_qm(struct bnx2x *bp, enum cos_mode mode,
263				       struct priority_cos *traffic_cos)
264{
265	bnx2x_map_q_cos(bp, BNX2X_FCOE_Q,
266			traffic_cos[LLFC_TRAFFIC_TYPE_FCOE].cos);
267	bnx2x_map_q_cos(bp, BNX2X_ISCSI_Q,
268			traffic_cos[LLFC_TRAFFIC_TYPE_ISCSI].cos);
269	bnx2x_map_q_cos(bp, BNX2X_ISCSI_ACK_Q,
270		traffic_cos[LLFC_TRAFFIC_TYPE_ISCSI].cos);
271	if (mode != STATIC_COS) {
272		/* required only in backward compatible COS mode */
273		bnx2x_map_q_cos(bp, BNX2X_ETH_Q,
274				traffic_cos[LLFC_TRAFFIC_TYPE_NW].cos);
275		bnx2x_map_q_cos(bp, BNX2X_TOE_Q,
276				traffic_cos[LLFC_TRAFFIC_TYPE_NW].cos);
277		bnx2x_map_q_cos(bp, BNX2X_TOE_ACK_Q,
278				traffic_cos[LLFC_TRAFFIC_TYPE_NW].cos);
279	}
280}
281
282
283/* congestion management port init api description
284 * the api works as follows:
285 * the driver should pass the cmng_init_input struct, the port_init function
286 * will prepare the required internal ram structure which will be passed back
287 * to the driver (cmng_init) that will write it into the internal ram.
288 *
289 * IMPORTANT REMARKS:
290 * 1. the cmng_init struct does not represent the contiguous internal ram
291 *    structure. the driver should use the XSTORM_CMNG_PERPORT_VARS_OFFSET
292 *    offset in order to write the port sub struct and the
293 *    PFID_FROM_PORT_AND_VNIC offset for writing the vnic sub struct (in other
294 *    words - don't use memcpy!).
295 * 2. although the cmng_init struct is filled for the maximal vnic number
296 *    possible, the driver should only write the valid vnics into the internal
297 *    ram according to the appropriate port mode.
298 */
299
300/* CMNG constants, as derived from system spec calculations */
301
302/* default MIN rate in case VNIC min rate is configured to zero- 100Mbps */
303#define DEF_MIN_RATE 100
304
305/* resolution of the rate shaping timer - 400 usec */
306#define RS_PERIODIC_TIMEOUT_USEC 400
307
308/* number of bytes in single QM arbitration cycle -
309 * coefficient for calculating the fairness timer
310 */
311#define QM_ARB_BYTES 160000
312
313/* resolution of Min algorithm 1:100 */
314#define MIN_RES 100
315
316/* how many bytes above threshold for
317 * the minimal credit of Min algorithm
318 */
319#define MIN_ABOVE_THRESH 32768
320
321/* Fairness algorithm integration time coefficient -
322 * for calculating the actual Tfair
323 */
324#define T_FAIR_COEF ((MIN_ABOVE_THRESH + QM_ARB_BYTES) * 8 * MIN_RES)
325
326/* Memory of fairness algorithm - 2 cycles */
327#define FAIR_MEM 2
328#define SAFC_TIMEOUT_USEC 52
329
330#define SDM_TICKS 4
331
332
333static inline void bnx2x_init_max(const struct cmng_init_input *input_data,
334				  u32 r_param, struct cmng_init *ram_data)
335{
336	u32 vnic;
337	struct cmng_vnic *vdata = &ram_data->vnic;
338	struct cmng_struct_per_port *pdata = &ram_data->port;
339	/* rate shaping per-port variables
340	 * 100 micro seconds in SDM ticks = 25
341	 * since each tick is 4 microSeconds
342	 */
343
344	pdata->rs_vars.rs_periodic_timeout =
345	RS_PERIODIC_TIMEOUT_USEC / SDM_TICKS;
346
347	/* this is the threshold below which no timer arming will occur.
348	 * 1.25 coefficient is for the threshold to be a little bigger
349	 * then the real time to compensate for timer in-accuracy
350	 */
351	pdata->rs_vars.rs_threshold =
352	(5 * RS_PERIODIC_TIMEOUT_USEC * r_param)/4;
353
354	/* rate shaping per-vnic variables */
355	for (vnic = 0; vnic < BNX2X_PORT2_MODE_NUM_VNICS; vnic++) {
356		/* global vnic counter */
357		vdata->vnic_max_rate[vnic].vn_counter.rate =
358		input_data->vnic_max_rate[vnic];
359		/* maximal Mbps for this vnic
360		 * the quota in each timer period - number of bytes
361		 * transmitted in this period
362		 */
363		vdata->vnic_max_rate[vnic].vn_counter.quota =
364			RS_PERIODIC_TIMEOUT_USEC *
365			(u32)vdata->vnic_max_rate[vnic].vn_counter.rate / 8;
366	}
367
368}
369
370static inline void bnx2x_init_min(const struct cmng_init_input *input_data,
371				  u32 r_param, struct cmng_init *ram_data)
372{
373	u32 vnic, fair_periodic_timeout_usec, vnicWeightSum, tFair;
374	struct cmng_vnic *vdata = &ram_data->vnic;
375	struct cmng_struct_per_port *pdata = &ram_data->port;
376
377	/* this is the resolution of the fairness timer */
378	fair_periodic_timeout_usec = QM_ARB_BYTES / r_param;
379
380	/* fairness per-port variables
381	 * for 10G it is 1000usec. for 1G it is 10000usec.
382	 */
383	tFair = T_FAIR_COEF / input_data->port_rate;
384
385	/* this is the threshold below which we won't arm the timer anymore */
386	pdata->fair_vars.fair_threshold = QM_ARB_BYTES;
387
388	/* we multiply by 1e3/8 to get bytes/msec. We don't want the credits
389	 * to pass a credit of the T_FAIR*FAIR_MEM (algorithm resolution)
390	 */
391	pdata->fair_vars.upper_bound = r_param * tFair * FAIR_MEM;
392
393	/* since each tick is 4 microSeconds */
394	pdata->fair_vars.fairness_timeout =
395				fair_periodic_timeout_usec / SDM_TICKS;
396
397	/* calculate sum of weights */
398	vnicWeightSum = 0;
399
400	for (vnic = 0; vnic < BNX2X_PORT2_MODE_NUM_VNICS; vnic++)
401		vnicWeightSum += input_data->vnic_min_rate[vnic];
402
403	/* global vnic counter */
404	if (vnicWeightSum > 0) {
405		/* fairness per-vnic variables */
406		for (vnic = 0; vnic < BNX2X_PORT2_MODE_NUM_VNICS; vnic++) {
407			/* this is the credit for each period of the fairness
408			 * algorithm - number of bytes in T_FAIR (this vnic
409			 * share of the port rate)
410			 */
411			vdata->vnic_min_rate[vnic].vn_credit_delta =
412				(u32)input_data->vnic_min_rate[vnic] * 100 *
413				(T_FAIR_COEF / (8 * 100 * vnicWeightSum));
414			if (vdata->vnic_min_rate[vnic].vn_credit_delta <
415			    pdata->fair_vars.fair_threshold +
416			    MIN_ABOVE_THRESH) {
417				vdata->vnic_min_rate[vnic].vn_credit_delta =
418					pdata->fair_vars.fair_threshold +
419					MIN_ABOVE_THRESH;
420			}
421		}
422	}
423}
424
425static inline void bnx2x_init_fw_wrr(const struct cmng_init_input *input_data,
426				     u32 r_param, struct cmng_init *ram_data)
427{
428	u32 vnic, cos;
429	u32 cosWeightSum = 0;
430	struct cmng_vnic *vdata = &ram_data->vnic;
431	struct cmng_struct_per_port *pdata = &ram_data->port;
432
433	for (cos = 0; cos < MAX_COS_NUMBER; cos++)
434		cosWeightSum += input_data->cos_min_rate[cos];
435
436	if (cosWeightSum > 0) {
437
438		for (vnic = 0; vnic < BNX2X_PORT2_MODE_NUM_VNICS; vnic++) {
439			/* Since cos and vnic shouldn't work together the rate
440			 * to divide between the coses is the port rate.
441			 */
442			u32 *ccd = vdata->vnic_min_rate[vnic].cos_credit_delta;
443			for (cos = 0; cos < MAX_COS_NUMBER; cos++) {
444				/* this is the credit for each period of
445				 * the fairness algorithm - number of bytes
446				 * in T_FAIR (this cos share of the vnic rate)
447				 */
448				ccd[cos] =
449				    (u32)input_data->cos_min_rate[cos] * 100 *
450				    (T_FAIR_COEF / (8 * 100 * cosWeightSum));
451				if (ccd[cos] < pdata->fair_vars.fair_threshold
452						+ MIN_ABOVE_THRESH) {
453					ccd[cos] =
454					    pdata->fair_vars.fair_threshold +
455					    MIN_ABOVE_THRESH;
456				}
457			}
458		}
459	}
460}
461
462static inline void bnx2x_init_safc(const struct cmng_init_input *input_data,
463				   struct cmng_init *ram_data)
464{
465	/* in microSeconds */
466	ram_data->port.safc_vars.safc_timeout_usec = SAFC_TIMEOUT_USEC;
467}
468
469/* Congestion management port init */
470static inline void bnx2x_init_cmng(const struct cmng_init_input *input_data,
471				   struct cmng_init *ram_data)
472{
473	u32 r_param;
474	memset(ram_data, 0, sizeof(struct cmng_init));
475
476	ram_data->port.flags = input_data->flags;
477
478	/* number of bytes transmitted in a rate of 10Gbps
479	 * in one usec = 1.25KB.
480	 */
481	r_param = BITS_TO_BYTES(input_data->port_rate);
482	bnx2x_init_max(input_data, r_param, ram_data);
483	bnx2x_init_min(input_data, r_param, ram_data);
484	bnx2x_init_fw_wrr(input_data, r_param, ram_data);
485	bnx2x_init_safc(input_data, ram_data);
486}
487
488
489
490/* Returns the index of start or end of a specific block stage in ops array */
491#define BLOCK_OPS_IDX(block, stage, end) \
492			(2*(((block)*NUM_OF_INIT_PHASES) + (stage)) + (end))
493
494
495#define INITOP_SET		0	/* set the HW directly */
496#define INITOP_CLEAR		1	/* clear the HW directly */
497#define INITOP_INIT		2	/* set the init-value array */
498
499/****************************************************************************
500* ILT management
501****************************************************************************/
502struct ilt_line {
503	dma_addr_t page_mapping;
504	void *page;
505	u32 size;
506};
507
508struct ilt_client_info {
509	u32 page_size;
510	u16 start;
511	u16 end;
512	u16 client_num;
513	u16 flags;
514#define ILT_CLIENT_SKIP_INIT	0x1
515#define ILT_CLIENT_SKIP_MEM	0x2
516};
517
518struct bnx2x_ilt {
519	u32 start_line;
520	struct ilt_line		*lines;
521	struct ilt_client_info	clients[4];
522#define ILT_CLIENT_CDU	0
523#define ILT_CLIENT_QM	1
524#define ILT_CLIENT_SRC	2
525#define ILT_CLIENT_TM	3
526};
527
528/****************************************************************************
529* SRC configuration
530****************************************************************************/
531struct src_ent {
532	u8 opaque[56];
533	u64 next;
534};
535
536/****************************************************************************
537* Parity configuration
538****************************************************************************/
539#define BLOCK_PRTY_INFO(block, en_mask, m1, m1h, m2, m3) \
540{ \
541	block##_REG_##block##_PRTY_MASK, \
542	block##_REG_##block##_PRTY_STS_CLR, \
543	en_mask, {m1, m1h, m2, m3}, #block \
544}
545
546#define BLOCK_PRTY_INFO_0(block, en_mask, m1, m1h, m2, m3) \
547{ \
548	block##_REG_##block##_PRTY_MASK_0, \
549	block##_REG_##block##_PRTY_STS_CLR_0, \
550	en_mask, {m1, m1h, m2, m3}, #block"_0" \
551}
552
553#define BLOCK_PRTY_INFO_1(block, en_mask, m1, m1h, m2, m3) \
554{ \
555	block##_REG_##block##_PRTY_MASK_1, \
556	block##_REG_##block##_PRTY_STS_CLR_1, \
557	en_mask, {m1, m1h, m2, m3}, #block"_1" \
558}
559
560static const struct {
561	u32 mask_addr;
562	u32 sts_clr_addr;
563	u32 en_mask;		/* Mask to enable parity attentions */
564	struct {
565		u32 e1;		/* 57710 */
566		u32 e1h;	/* 57711 */
567		u32 e2;		/* 57712 */
568		u32 e3;		/* 578xx */
569	} reg_mask;		/* Register mask (all valid bits) */
570	char name[8];		/* Block's longest name is 7 characters long
571				 * (name + suffix)
572				 */
573} bnx2x_blocks_parity_data[] = {
574	/* bit 19 masked */
575	/* REG_WR(bp, PXP_REG_PXP_PRTY_MASK, 0x80000); */
576	/* bit 5,18,20-31 */
577	/* REG_WR(bp, PXP2_REG_PXP2_PRTY_MASK_0, 0xfff40020); */
578	/* bit 5 */
579	/* REG_WR(bp, PXP2_REG_PXP2_PRTY_MASK_1, 0x20);	*/
580	/* REG_WR(bp, HC_REG_HC_PRTY_MASK, 0x0); */
581	/* REG_WR(bp, MISC_REG_MISC_PRTY_MASK, 0x0); */
582
583	/* Block IGU, MISC, PXP and PXP2 parity errors as long as we don't
584	 * want to handle "system kill" flow at the moment.
585	 */
586	BLOCK_PRTY_INFO(PXP, 0x7ffffff, 0x3ffffff, 0x3ffffff, 0x7ffffff,
587			0x7ffffff),
588	BLOCK_PRTY_INFO_0(PXP2,	0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
589			  0xffffffff),
590	BLOCK_PRTY_INFO_1(PXP2,	0x1ffffff, 0x7f, 0x7f, 0x7ff, 0x1ffffff),
591	BLOCK_PRTY_INFO(HC, 0x7, 0x7, 0x7, 0, 0),
592	BLOCK_PRTY_INFO(NIG, 0xffffffff, 0x3fffffff, 0xffffffff, 0, 0),
593	BLOCK_PRTY_INFO_0(NIG,	0xffffffff, 0, 0, 0xffffffff, 0xffffffff),
594	BLOCK_PRTY_INFO_1(NIG,	0xffff, 0, 0, 0xff, 0xffff),
595	BLOCK_PRTY_INFO(IGU, 0x7ff, 0, 0, 0x7ff, 0x7ff),
596	BLOCK_PRTY_INFO(MISC, 0x1, 0x1, 0x1, 0x1, 0x1),
597	BLOCK_PRTY_INFO(QM, 0, 0x1ff, 0xfff, 0xfff, 0xfff),
598	BLOCK_PRTY_INFO(ATC, 0x1f, 0, 0, 0x1f, 0x1f),
599	BLOCK_PRTY_INFO(PGLUE_B, 0x3, 0, 0, 0x3, 0x3),
600	BLOCK_PRTY_INFO(DORQ, 0, 0x3, 0x3, 0x3, 0x3),
601	{GRCBASE_UPB + PB_REG_PB_PRTY_MASK,
602		GRCBASE_UPB + PB_REG_PB_PRTY_STS_CLR, 0xf,
603		{0xf, 0xf, 0xf, 0xf}, "UPB"},
604	{GRCBASE_XPB + PB_REG_PB_PRTY_MASK,
605		GRCBASE_XPB + PB_REG_PB_PRTY_STS_CLR, 0,
606		{0xf, 0xf, 0xf, 0xf}, "XPB"},
607	BLOCK_PRTY_INFO(SRC, 0x4, 0x7, 0x7, 0x7, 0x7),
608	BLOCK_PRTY_INFO(CDU, 0, 0x1f, 0x1f, 0x1f, 0x1f),
609	BLOCK_PRTY_INFO(CFC, 0, 0xf, 0xf, 0xf, 0x3f),
610	BLOCK_PRTY_INFO(DBG, 0, 0x1, 0x1, 0x1, 0x1),
611	BLOCK_PRTY_INFO(DMAE, 0, 0xf, 0xf, 0xf, 0xf),
612	BLOCK_PRTY_INFO(BRB1, 0, 0xf, 0xf, 0xf, 0xf),
613	BLOCK_PRTY_INFO(PRS, (1<<6), 0xff, 0xff, 0xff, 0xff),
614	BLOCK_PRTY_INFO(PBF, 0, 0, 0x3ffff, 0xfffff, 0xfffffff),
615	BLOCK_PRTY_INFO(TM, 0, 0, 0x7f, 0x7f, 0x7f),
616	BLOCK_PRTY_INFO(TSDM, 0x18, 0x7ff, 0x7ff, 0x7ff, 0x7ff),
617	BLOCK_PRTY_INFO(CSDM, 0x8, 0x7ff, 0x7ff, 0x7ff, 0x7ff),
618	BLOCK_PRTY_INFO(USDM, 0x38, 0x7ff, 0x7ff, 0x7ff, 0x7ff),
619	BLOCK_PRTY_INFO(XSDM, 0x8, 0x7ff, 0x7ff, 0x7ff, 0x7ff),
620	BLOCK_PRTY_INFO(TCM, 0, 0, 0x7ffffff, 0x7ffffff, 0x7ffffff),
621	BLOCK_PRTY_INFO(CCM, 0, 0, 0x7ffffff, 0x7ffffff, 0x7ffffff),
622	BLOCK_PRTY_INFO(UCM, 0, 0, 0x7ffffff, 0x7ffffff, 0x7ffffff),
623	BLOCK_PRTY_INFO(XCM, 0, 0, 0x3fffffff, 0x3fffffff, 0x3fffffff),
624	BLOCK_PRTY_INFO_0(TSEM, 0, 0xffffffff, 0xffffffff, 0xffffffff,
625			  0xffffffff),
626	BLOCK_PRTY_INFO_1(TSEM, 0, 0x3, 0x1f, 0x3f, 0x3f),
627	BLOCK_PRTY_INFO_0(USEM, 0, 0xffffffff, 0xffffffff, 0xffffffff,
628			  0xffffffff),
629	BLOCK_PRTY_INFO_1(USEM, 0, 0x3, 0x1f, 0x1f, 0x1f),
630	BLOCK_PRTY_INFO_0(CSEM, 0, 0xffffffff, 0xffffffff, 0xffffffff,
631			  0xffffffff),
632	BLOCK_PRTY_INFO_1(CSEM, 0, 0x3, 0x1f, 0x1f, 0x1f),
633	BLOCK_PRTY_INFO_0(XSEM, 0, 0xffffffff, 0xffffffff, 0xffffffff,
634			  0xffffffff),
635	BLOCK_PRTY_INFO_1(XSEM, 0, 0x3, 0x1f, 0x3f, 0x3f),
636};
637
638
639/* [28] MCP Latched rom_parity
640 * [29] MCP Latched ump_rx_parity
641 * [30] MCP Latched ump_tx_parity
642 * [31] MCP Latched scpad_parity
643 */
644#define MISC_AEU_ENABLE_MCP_PRTY_SUB_BITS	\
645	(AEU_INPUTS_ATTN_BITS_MCP_LATCHED_ROM_PARITY | \
646	 AEU_INPUTS_ATTN_BITS_MCP_LATCHED_UMP_RX_PARITY | \
647	 AEU_INPUTS_ATTN_BITS_MCP_LATCHED_UMP_TX_PARITY)
648
649#define MISC_AEU_ENABLE_MCP_PRTY_BITS	\
650	(MISC_AEU_ENABLE_MCP_PRTY_SUB_BITS | \
651	 AEU_INPUTS_ATTN_BITS_MCP_LATCHED_SCPAD_PARITY)
652
653/* Below registers control the MCP parity attention output. When
654 * MISC_AEU_ENABLE_MCP_PRTY_BITS are set - attentions are
655 * enabled, when cleared - disabled.
656 */
657static const struct {
658	u32 addr;
659	u32 bits;
660} mcp_attn_ctl_regs[] = {
661	{ MISC_REG_AEU_ENABLE4_FUNC_0_OUT_0,
662		MISC_AEU_ENABLE_MCP_PRTY_BITS },
663	{ MISC_REG_AEU_ENABLE4_NIG_0,
664		MISC_AEU_ENABLE_MCP_PRTY_SUB_BITS },
665	{ MISC_REG_AEU_ENABLE4_PXP_0,
666		MISC_AEU_ENABLE_MCP_PRTY_SUB_BITS },
667	{ MISC_REG_AEU_ENABLE4_FUNC_1_OUT_0,
668		MISC_AEU_ENABLE_MCP_PRTY_BITS },
669	{ MISC_REG_AEU_ENABLE4_NIG_1,
670		MISC_AEU_ENABLE_MCP_PRTY_SUB_BITS },
671	{ MISC_REG_AEU_ENABLE4_PXP_1,
672		MISC_AEU_ENABLE_MCP_PRTY_SUB_BITS }
673};
674
675static inline void bnx2x_set_mcp_parity(struct bnx2x *bp, u8 enable)
676{
677	int i;
678	u32 reg_val;
679
680	for (i = 0; i < ARRAY_SIZE(mcp_attn_ctl_regs); i++) {
681		reg_val = REG_RD(bp, mcp_attn_ctl_regs[i].addr);
682
683		if (enable)
684			reg_val |= mcp_attn_ctl_regs[i].bits;
685		else
686			reg_val &= ~mcp_attn_ctl_regs[i].bits;
687
688		REG_WR(bp, mcp_attn_ctl_regs[i].addr, reg_val);
689	}
690}
691
692static inline u32 bnx2x_parity_reg_mask(struct bnx2x *bp, int idx)
693{
694	if (CHIP_IS_E1(bp))
695		return bnx2x_blocks_parity_data[idx].reg_mask.e1;
696	else if (CHIP_IS_E1H(bp))
697		return bnx2x_blocks_parity_data[idx].reg_mask.e1h;
698	else if (CHIP_IS_E2(bp))
699		return bnx2x_blocks_parity_data[idx].reg_mask.e2;
700	else /* CHIP_IS_E3 */
701		return bnx2x_blocks_parity_data[idx].reg_mask.e3;
702}
703
704static inline void bnx2x_disable_blocks_parity(struct bnx2x *bp)
705{
706	int i;
707
708	for (i = 0; i < ARRAY_SIZE(bnx2x_blocks_parity_data); i++) {
709		u32 dis_mask = bnx2x_parity_reg_mask(bp, i);
710
711		if (dis_mask) {
712			REG_WR(bp, bnx2x_blocks_parity_data[i].mask_addr,
713			       dis_mask);
714			DP(NETIF_MSG_HW, "Setting parity mask "
715						 "for %s to\t\t0x%x\n",
716				    bnx2x_blocks_parity_data[i].name, dis_mask);
717		}
718	}
719
720	/* Disable MCP parity attentions */
721	bnx2x_set_mcp_parity(bp, false);
722}
723
724/* Clear the parity error status registers. */
725static inline void bnx2x_clear_blocks_parity(struct bnx2x *bp)
726{
727	int i;
728	u32 reg_val, mcp_aeu_bits =
729		AEU_INPUTS_ATTN_BITS_MCP_LATCHED_ROM_PARITY |
730		AEU_INPUTS_ATTN_BITS_MCP_LATCHED_SCPAD_PARITY |
731		AEU_INPUTS_ATTN_BITS_MCP_LATCHED_UMP_RX_PARITY |
732		AEU_INPUTS_ATTN_BITS_MCP_LATCHED_UMP_TX_PARITY;
733
734	/* Clear SEM_FAST parities */
735	REG_WR(bp, XSEM_REG_FAST_MEMORY + SEM_FAST_REG_PARITY_RST, 0x1);
736	REG_WR(bp, TSEM_REG_FAST_MEMORY + SEM_FAST_REG_PARITY_RST, 0x1);
737	REG_WR(bp, USEM_REG_FAST_MEMORY + SEM_FAST_REG_PARITY_RST, 0x1);
738	REG_WR(bp, CSEM_REG_FAST_MEMORY + SEM_FAST_REG_PARITY_RST, 0x1);
739
740	for (i = 0; i < ARRAY_SIZE(bnx2x_blocks_parity_data); i++) {
741		u32 reg_mask = bnx2x_parity_reg_mask(bp, i);
742
743		if (reg_mask) {
744			reg_val = REG_RD(bp, bnx2x_blocks_parity_data[i].
745					 sts_clr_addr);
746			if (reg_val & reg_mask)
747				DP(NETIF_MSG_HW,
748					    "Parity errors in %s: 0x%x\n",
749					    bnx2x_blocks_parity_data[i].name,
750					    reg_val & reg_mask);
751		}
752	}
753
754	/* Check if there were parity attentions in MCP */
755	reg_val = REG_RD(bp, MISC_REG_AEU_AFTER_INVERT_4_MCP);
756	if (reg_val & mcp_aeu_bits)
757		DP(NETIF_MSG_HW, "Parity error in MCP: 0x%x\n",
758		   reg_val & mcp_aeu_bits);
759
760	/* Clear parity attentions in MCP:
761	 * [7]  clears Latched rom_parity
762	 * [8]  clears Latched ump_rx_parity
763	 * [9]  clears Latched ump_tx_parity
764	 * [10] clears Latched scpad_parity (both ports)
765	 */
766	REG_WR(bp, MISC_REG_AEU_CLR_LATCH_SIGNAL, 0x780);
767}
768
769static inline void bnx2x_enable_blocks_parity(struct bnx2x *bp)
770{
771	int i;
772
773	for (i = 0; i < ARRAY_SIZE(bnx2x_blocks_parity_data); i++) {
774		u32 reg_mask = bnx2x_parity_reg_mask(bp, i);
775
776		if (reg_mask)
777			REG_WR(bp, bnx2x_blocks_parity_data[i].mask_addr,
778				bnx2x_blocks_parity_data[i].en_mask & reg_mask);
779	}
780
781	/* Enable MCP parity attentions */
782	bnx2x_set_mcp_parity(bp, true);
783}
784
785
786#endif /* BNX2X_INIT_H */
787
788