summaryrefslogtreecommitdiffstats
path: root/include/chip.h
blob: d6e7e355bf7798311107f2ed399f9184cdd17905 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
/* Copyright 2013-2014 IBM Corp.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * 	http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
 * implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef __CHIP_H
#define __CHIP_H

#include <stdint.h>
#include <lock.h>

#include <ccan/list/list.h>

/*
 * Note on chip IDs:
 *
 * We carry a "chip_id" around, in the cpu_thread, but also as
 * ibm,chip-id properties.
 *
 * This ID is the HW fabric ID of a chip based on the XSCOM numbering,
 * also known as "GCID" (Global Chip ID).
 *
 * The format of this number is different between P7 and P8 and care must
 * be taken when trying to convert between this chip ID and some other
 * representation such as PIR values, interrupt-server numbers etc... :
 *
 * P7 GCID
 * -------
 *
 * Global chip ID is a 6 bit number:
 *
 *     NodeID    T   ChipID
 * |           |   |       |
 * |___|___|___|___|___|___|
 *
 * Where T is the "torrent" bit and is 0 for P7 chips and 1 for
 * directly XSCOM'able IO chips such as Torrent
 *
 * This macro converts a PIR to a GCID
 */
#define P7_PIR2GCID(pir) ({ 				\
	uint32_t _pir = pir;				\
	((_pir >> 4) & 0x38) | ((_pir >> 5) & 0x3); })

#define P7_PIR2COREID(pir) (((pir) >> 2) & 0x7)

#define P7_PIR2THREADID(pir) ((pir) & 0x3)

/*
 * P8 GCID
 * -------
 *
 * Global chip ID is a 6 bit number:
 *
 *     NodeID      ChipID
 * |           |           |
 * |___|___|___|___|___|___|
 *
 * The difference with P7 is the absence of T bit, the ChipID
 * is 3 bits long. The GCID is thus the same as the high bits
 * if the PIR
 */
#define P8_PIR2GCID(pir) (((pir) >> 7) & 0x3f)

#define P8_PIR2COREID(pir) (((pir) >> 3) & 0xf)

#define P8_PIR2THREADID(pir) ((pir) & 0x7)

/*
 * P9 GCID
 * -------
 *
 * Global chip ID is a 7 bit number:
 *
 *        NodeID      ChipID
 * |               |           |
 * |___|___|___|___|___|___|___|
 *
 * Bit 56 is unused according to the manual by we add it to the coreid here,
 * thus we have a 6-bit core number.
 *
 * Note: XIVE Only supports 4-bit chip numbers ...
 */
#define P9_PIR2GCID(pir) (((pir) >> 8) & 0x7f)

#define P9_PIR2COREID(pir) (((pir) >> 2) & 0x3f)

#define P9_PIR2THREADID(pir) ((pir) & 0x3)

#define P9_GCID2NODEID(gcid)	(((gcid) >> 3) & 0xf)

#define P9_GCID2CHIPID(gcid) ((gcid) & 0x7)

/* P9 specific ones mostly used by XIVE */
#define P9_PIR2LOCALCPU(pir) ((pir) & 0xff)
#define P9_PIRFROMLOCALCPU(chip, cpu)	(((chip) << 8) | (cpu))


struct dt_node;
struct centaur_chip;
struct mfsi;
struct xive;
struct lpcm;
struct vas;
struct p9_sbe;

/* Chip type */
enum proc_chip_type {
	PROC_CHIP_UNKNOWN,
	PROC_CHIP_P7,
	PROC_CHIP_P7P,
	PROC_CHIP_P8_MURANO,
	PROC_CHIP_P8_VENICE,
	PROC_CHIP_P8_NAPLES,
	PROC_CHIP_P9_NIMBUS,
	PROC_CHIP_P9_CUMULUS,
	PROC_CHIP_P9P,
};

/* Simulator quirks */
enum proc_chip_quirks {
	QUIRK_NO_CHIPTOD	= 0x00000001,
	QUIRK_MAMBO_CALLOUTS	= 0x00000002,
	QUIRK_NO_F000F		= 0x00000004,
	QUIRK_NO_PBA		= 0x00000008,
	QUIRK_NO_OCC_IRQ       	= 0x00000010,
	QUIRK_SIMICS		= 0x00000020,
	QUIRK_SLOW_SIM		= 0x00000040,
	QUIRK_NO_DIRECT_CTL	= 0x00000080,
	QUIRK_NO_RNG		= 0x00000100,
};

extern enum proc_chip_quirks proc_chip_quirks;

static inline bool chip_quirk(unsigned int q)
{
	return !!(proc_chip_quirks & q);
}

#define MAX_CHIPS	(1 << 6)	/* 6-bit chip ID */

/*
 * For each chip in the system, we maintain this structure
 *
 * This contains fields used by different modules including
 * modules in hw/ but is handy to keep per-chip data
 */
struct proc_chip {
	uint32_t		id;		/* HW Chip ID (GCID) */
	struct dt_node		*devnode;	/* "xscom" chip node */

	/* These are only initialized after xcom_init */
	enum proc_chip_type	type;
	uint32_t		ec_level;	/* 0xMm (DD1.0 = 0x10) */
	uint8_t                 ec_rev;		/* sub-revision */

	/* Those two values are only populated on machines with an FSP
	 * dbob_id = Drawer/Block/Octant/Blade (DBOBID)
	 * pcid    = HDAT processor_chip_id
	 */
	uint32_t		dbob_id;
	uint32_t		pcid;

	/* If we expect to have an OCC (i.e. P8) and it is functional,
	 * set TRUE. If something has told us it is not, set FALSE and
	 * we can not wait for OCCs to init. This is only going to be
	 * FALSE in a simulator that doesn't simulate OCCs. */
	bool			occ_functional;

	/* Used by hw/xscom.c */
	uint64_t		xscom_base;

	/* Used by hw/lpc.c */
	struct lpcm		*lpc;

	/* Used by hw/slw.c */
	uint64_t		slw_base;
	uint64_t		slw_bar_size;
	uint64_t		slw_image_size;

	/* Used by hw/homer.c */
	uint64_t		homer_base;
	uint64_t		homer_size;
	uint64_t		occ_common_base;
	uint64_t		occ_common_size;
	uint8_t			throttle;

	/* Must hold capi_lock to change */
	uint8_t			capp_phb3_attached_mask;
	uint8_t			capp_ucode_loaded;

	/* Used by hw/centaur.c */
	struct centaur_chip	*centaurs;

	/* Used by hw/p8-i2c.c */
	struct list_head	i2cms;

	/* Used by hw/psi.c */
	struct psi		*psi;

	/* Used by hw/fsi-master.c */
	struct mfsi		*fsi_masters;

	/* Used by hw/xive.c */
	struct xive		*xive;

	struct vas		*vas;

	/* Used by hw/nx-compress.c */
	uint64_t		nx_base;
	/* location code of this chip */
	const uint8_t		*loc_code;

	/* Used by hw/sbe-p9.c */
	struct p9_sbe		*sbe;
};

extern uint32_t pir_to_chip_id(uint32_t pir);
extern uint32_t pir_to_core_id(uint32_t pir);
extern uint32_t pir_to_thread_id(uint32_t pir);

extern struct proc_chip *next_chip(struct proc_chip *chip);

#define for_each_chip(__c) for (__c=next_chip(NULL); __c; __c=next_chip(__c))

extern struct proc_chip *get_chip(uint32_t chip_id);

extern void init_chips(void);

/* helper to get number of chips in the system */
static inline int nr_chips(void)
{
	struct proc_chip *chip;
	int nr_chips = 0;

	for_each_chip(chip)
		nr_chips++;

	return nr_chips;
}

/* helper to get location code of a chip */
static inline const char *chip_loc_code(uint32_t chip_id)
{
	struct proc_chip *chip;

	chip = get_chip(chip_id);
	if (!chip)
		return NULL;

	return chip->loc_code;
}

#endif /* __CHIP_H */

OpenPOWER on IntegriCloud