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
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
|
// @file cmdh_fsp.h
// @brief Command Handling for FSP Communication.
/******************************************************************************
*
* @page ChangeLogs Change Logs
* @section _cmdh_fsp_h cmdh_fsp.h
* @verbatim
*
* Flag Def/Fea Userid Date Description
* ------- ---------- -------- ---------- ----------------------------------
* thallet 04/05/2012 Created
* @th022 thallet 10/08/2012 Moved data commands to separate file
* @th036 881677 thallet 05/06/2013 New Poll Command Support
* @th039 887066 thallet 06/11/2013 FSP Comm Improvements for Attn
* @at015 885884 alvinwan 06/10/2013 Support Observation/Active state change
* @gm010 901580 milesg 10/06/2013 Low Level FFDC support
* @sb002 908891 sbroyles 12/09/2013 FFDC updates
* @gm022 908890 milesg 01/23/2014 Halt OCC on OCCLFIR[38]
* @gs041 942203 gjsilva 10/17/2014 Support for HTMGT/BMC interface
*
* @endverbatim
*
*///*************************************************************************/
#ifndef _CMDH_FSP_H
#define _CMDH_FSP_H
//*************************************************************************
// Includes
//*************************************************************************
#include "cmdh_service_codes.h"
#include "errl.h"
#include "trac.h"
#include "rtls.h"
#include "occ_common.h"
#include "state.h"
//*************************************************************************
// Defines/Enums
//*************************************************************************
// Register Addresses for Mailbox 1 Doorbell Status/Control
#define MAILBOX_1_DOORBELL_STS_CTRL_REGADDR 0x00050020
// Register Addresses for (unused) Mailbox 1 Header Buffer
#define MAILBOX_1_HEADER_COMMAND_BASE 0x00050021
#define MAILBOX_1_HEADER_COMMAND_0_A_REGADDR (0 + MAILBOX_1_HEADER_COMMAND_BASE)
#define MAILBOX_1_HEADER_COMMAND_1_A_REGADDR (1 + MAILBOX_1_HEADER_COMMAND_BASE)
#define MAILBOX_1_HEADER_COMMAND_2_A_REGADDR (2 + MAILBOX_1_HEADER_COMMAND_BASE)
// Register Addresses for Mailbox 1 Data Buffer
#define MAILBOX_1_DATA_AREA_A_BASE 0x00050040
#define MAILBOX_1_DATA_AREA_A_0_REGADDR (0 + MAILBOX_1_DATA_AREA_A_BASE)
#define MAILBOX_1_DATA_AREA_A_1_REGADDR (1 + MAILBOX_1_DATA_AREA_A_BASE)
#define MAILBOX_1_DATA_AREA_A_2_REGADDR (2 + MAILBOX_1_DATA_AREA_A_BASE)
#define MAILBOX_1_DATA_AREA_A_3_REGADDR (3 + MAILBOX_1_DATA_AREA_A_BASE)
#define MAILBOX_1_DATA_AREA_A_4_REGADDR (4 + MAILBOX_1_DATA_AREA_A_BASE)
#define MAILBOX_1_DATA_AREA_A_5_REGADDR (5 + MAILBOX_1_DATA_AREA_A_BASE)
#define MAILBOX_1_DATA_AREA_A_6_REGADDR (6 + MAILBOX_1_DATA_AREA_A_BASE)
#define MAILBOX_1_DATA_AREA_A_7_REGADDR (7 + MAILBOX_1_DATA_AREA_A_BASE)
#define MAILBOX_1_DATA_AREA_A_8_REGADDR (8 + MAILBOX_1_DATA_AREA_A_BASE)
#define MAILBOX_1_DATA_AREA_A_9_REGADDR (9 + MAILBOX_1_DATA_AREA_A_BASE)
// Command/Response Common: DataLength Field Size - 2 bytes
#define CMDH_FSP_DATALEN_SIZE 2
// Command/Response Common: Checksum Field Size - 2 bytes
#define CMDH_FSP_CHECKSUM_SIZE 2
// Command: Full Buffer Size - 4 kB
#define CMDH_FSP_CMD_SIZE 4096
// Command: Seq + Cmd - 2 bytes
#define CMDH_FSP_SEQ_CMD_SIZE 2
// Command: Maximum "Data" Field Length
#define CMDH_FSP_CMD_DATA_SIZE (CMDH_FSP_CMD_SIZE - \
CMDH_FSP_DATALEN_SIZE - \
CMDH_FSP_CHECKSUM_SIZE - \
CMDH_FSP_SEQ_CMD_SIZE )
// Response: Full Buffer Size - 4 kB
#define CMDH_FSP_RSP_SIZE 4096
// Response: Seq + Cmd + RC - 3 bytes
#define CMDH_FSP_SEQ_CMD_RC_SIZE 3
// Response: Maximum "Data" Field Length
#define CMDH_FSP_RSP_DATA_SIZE (CMDH_FSP_RSP_SIZE - \
CMDH_FSP_DATALEN_SIZE - \
CMDH_FSP_CHECKSUM_SIZE - \
CMDH_FSP_SEQ_CMD_RC_SIZE )
// Sender IDs of an attention to the OCC
#define ATTN_SENDER_ID_FSP 0x01
#define ATTN_SENDER_ID_HTMGT 0x10
#define ATTN_SENDER_ID_BMC 0x20
// Attention type of an attention to the OCC
#define ATTN_TYPE_CMD_WRITE 0x01
// OCC/HTMGT command buffer offset in HOMER
#define OCC_HTMGT_CMD_OFFSET_HOMER 0x001EE000
// OCC/HTMGT response buffer offset in HOMER
#define OCC_HTMGT_RSP_OFFSET_HOMER 0x001EF000
/**
* @enum eFspAlertType
* @brief Typedef of the various alerts that OCC can send TMGT
*/
typedef enum
{
///OCC has a response ready for TMGT to come get
OCC_ALERT_FSP_RESP_READY = 1,
///OCC alert to TMGT that it needs to poll OCC
OCC_ALERT_FSP_SERVICE_REQD = 2,
///OCC alert to TMGT that it sees a checkstop
OCC_ALERT_SYS_CHECKSTOP = 3,
} eFspAlertType;
/**
* @enum eFsi2HostMboxState
* @brief States for OCC using the Mailbox for Attn
*/
typedef enum
{
FSI2HOST_MBOX_NOT_USEABLE = 0,
FSI2HOST_MBOX_INITIALIZED = 1,
} eFsi2HostMboxState; // @th036
/**
* @enum eCmdhWakeupThreadMask
* @brief Typedef of the various reasons why the cmdh thread wakes up
*/
typedef enum
{
/// Success, alert was sent
CMDH_WAKEUP_REASON_NONE = 0x00000000,
CMDH_WAKEUP_FSP_COMMAND = 0x00000001,
CMDH_WAKEUP_FSP_ATTENTION_ALERT = 0x00000002,
CMDH_WAKEUP_FSP_CHECKSTOP_ALERT = 0x00000004,
} eCmdhWakeupThreadMask;
/**
* @enum eFspAlertRc
* @brief Typedef of the various errors that can happen on alerts
*/
typedef enum
{
/// Success, alert was sent
OCC_ALERT_SUCCESS = 0,
///SCOM Failure, Return PCB Error code
OCC_ALERT_SCOM_FAILURE_RSVD_0 = 1, // Resource Occupied
OCC_ALERT_SCOM_FAILURE_RSVD_1 = 2, // Chiplet Offline
OCC_ALERT_SCOM_FAILURE_RSVD_2 = 3, // Partial Good
OCC_ALERT_SCOM_FAILURE_RSVD_4 = 4, // Address Error
OCC_ALERT_SCOM_FAILURE_RSVD_5 = 5, // Clock Error
OCC_ALERT_SCOM_FAILURE_RSVD_6 = 6, // Packet Error
OCC_ALERT_SCOM_FAILURE_RSVD_7 = 7, // Timeout
///Failure due to lbus_slaveA_pending bit being set
/// (meaning that FSP hasn't gotten last message)
OCC_ALERT_LAST_ATTN_NOT_COMPLETE = 8,
} eFspAlertRc;
/**
* @enum ERRL_RC
* @brief Typedef of the various 1-byte error codes that a return packet may
* contain. Returning any value except for "Success" or "Conditional
* success" requires that the return packet to TMGT be an
* errl_generic_resp_t packet.
*/
typedef enum
{
///Success
ERRL_RC_SUCCESS = 0x00,
///Command was accepted and processed, however more processing may be needed
ERRL_RC_CONDITIONAL_SUCCESS = 0x01,
///The command type is invalid
ERRL_RC_INVALID_CMD = 0x11,
///The command data length is invalid for the particular command
ERRL_RC_INVALID_CMD_LEN = 0x12,
///The command data has an invalid value for a field
ERRL_RC_INVALID_DATA = 0x13,
///The command packet checksum is not correct
ERRL_RC_CHECKSUM_FAIL = 0x14,
///An error occurred within the TPMF to prevent the command processing
ERRL_RC_INTERNAL_FAIL = 0x15,
///The OCC cannot accept the command in its present state
ERRL_RC_INVALID_STATE = 0x16,
///This is a panic response
ERRL_RC_PANIC = 0xE0,
///This is a checkpoint response
ERRL_RC_INIT_CHCKPNT = 0xE1,
/// @sb002 Halting due to OCC watchdog timer expiration
ERRL_RC_WDOG_TIMER = 0xE2,
/// @sb002 Halting due to OCB timer expiration
ERRL_RC_OCB_TIMER = 0xE3,
/// @gm022 Halting due to unmasked OCCLFIR bit being set (see OISR0 bit 2)
ERRL_RC_OCC_HW_ERROR = 0xE4,
///The command is being processed by OCC
ERRL_RC_CMD_IN_PROGRESS = 0xFF,
} ERRL_RC;
//*************************************************************************
// Macros
//*************************************************************************
#define CMDH_DATALEN_FIELD_UINT16(cmdOrRspPtr) \
(CONVERT_UINT8_ARRAY_UINT16(cmdOrRspPtr->data_length[0], \
cmdOrRspPtr->data_length[1]))
//*************************************************************************
// Structures
//*************************************************************************
/**
* @struct cmdh_fsp_cmd_header
* @brief Faking out an inheritable anonymous struct definition, so it works
* with the same syntax that is used in C11 version of the C-standard
* Contains TMGT command common fields (seq, cmd, data_len)
*/
#define cmdh_fsp_cmd_header \
__attribute__ ((packed)) { \
uint8_t seq; \
uint8_t cmd_type; \
uint8_t data_length[CMDH_FSP_DATALEN_SIZE]; \
}
/**
* @struct cmdh_fsp_cmd_header_t
* @brief Contains TMGT command common fields (seq, cmd, data_len)
*
*/
typedef struct __attribute__ ((packed))
{
struct cmdh_fsp_cmd_header;
} cmdh_fsp_cmd_header_t;
/**
* @struct cmdh_fsp_cmd_t
* @brief Contains TMGT command fields
*
*/
typedef struct __attribute__ ((packed))
{
/// Response header that is the same for all commands..seq,cmd,rc,etc
struct cmdh_fsp_cmd_header;
/// Data bytes (here it is the max data size)
uint8_t data[CMDH_FSP_CMD_DATA_SIZE];
/// 2 bytes reserved for Checksum, although the checksum usually doesn't
/// actually go here in practice
uint8_t __checksum_rsvd[CMDH_FSP_CHECKSUM_SIZE];
}cmdh_fsp_cmd_t;
/**
* @struct cmdh_fsp_rsp_header
* @brief Faking out an inheritable anonymous struct definition, so it works
* with the same syntax that is used in C11 version of the C-standard
* Contains TMGT command common fields (seq, cmd, rc, data_len)
*/
#define cmdh_fsp_rsp_header \
__attribute__ ((packed)) { \
uint8_t seq; \
uint8_t cmd_type; \
uint8_t rc; \
uint8_t data_length[CMDH_FSP_DATALEN_SIZE]; \
}
/**
* @struct cmdh_fsp_rsp_header_t
* @brief Contains TMGT command common fields (seq, cmd, rc, data_len)
*
*/
typedef struct __attribute__ ((packed))
{
struct cmdh_fsp_rsp_header;
} cmdh_fsp_rsp_header_t;
/**
* @struct cmdh_fsp_rsp_t
* @brief Contains TMGT command response fields
*
*/
typedef struct __attribute__ ((packed))
{
/// Response header that is the same for all commands..seq,cmd,rc,etc
struct cmdh_fsp_rsp_header;
/// Data bytes (here it is the max data size)
uint8_t data[CMDH_FSP_RSP_DATA_SIZE];
/// 2 bytes reserved for Checksum, although the checksum usually doesn't
/// actually go here in practice
uint8_t __checksum_rsvd[CMDH_FSP_CHECKSUM_SIZE];
}cmdh_fsp_rsp_t;
/**
* @struct fsp_cmd_t
* @brief Contains "data" fields needed to receive/parse a command from TMGT
*
*/
typedef struct
{
union
{
/// Accessible as response fields split up..seq, cmd, etc
cmdh_fsp_cmd_t fields;
/// Accessible as byte array for checksum, etc.
uint8_t byte[CMDH_FSP_CMD_SIZE];
};
} fsp_cmd_t;
/**
* @struct fsp_rsp_t
* @brief Contains "data" fields needed to respond to a command from TMGT
*
*/
typedef struct
{
union
{
/// Accessible as response fields split up..seq, cmd, rc, etc
cmdh_fsp_rsp_t fields;
/// Accessible as byte array for checksum, etc.
uint8_t byte[CMDH_FSP_CMD_SIZE];
};
} fsp_rsp_t;
/**
* @struct fsp_msg_t
* @brief Contains "data" needed to handle a command to/from TMGT
*
*/
typedef struct __attribute__ ((packed))
{
/// Pointer to FSP->OCC Command Buffer
fsp_cmd_t * cmd;
/// Pointer to FSP->OCC Response Buffer
fsp_rsp_t * rsp;
/// Placeholder for the 8 bytes of doorbell data that is automatically
/// sent as part of the doorbell from FSP
uint8_t doorbell[8];
} fsp_msg_t;
extern fsp_msg_t G_fsp_msg;
//---------------------------------------------------------
// Generic Error Response
//---------------------------------------------------------
/**
* @struct errl_generic_resp
* @brief Typedef of a generic failure response packet to TMGT. Any command
* handler may return this packet in place of its normal return packet.
*/
typedef struct errl_generic_resp {
/// Header that is the same for any TMGT response
struct cmdh_fsp_rsp_header;
/// Any non-zero value indicates the log id associated with a TPMF error log
uint8_t log_id;
/// Command Checksum, supplied by CMDH
uint8_t checksum[2];
} errl_generic_resp_t;
//---------------------------------------------------------
// Mailbox Register Definition
//---------------------------------------------------------
/**
* @struct doorbl_stsctrl_reg_t
* @brief Breakdown of the Mailbox1 Status/Control Reg, which OCC uses
* to alert TMGT.
*/
typedef struct
{
union
{
struct {
#if 1
uint64_t permission_to_send :1;
uint64_t abort :1;
uint64_t lbus_slaveA_pending :1;
uint64_t pib_slaveB_pending :1;
uint64_t _reserved_1 :1;
uint64_t xdn :1;
uint64_t xup :1;
uint64_t _reserved_2 :1;
uint64_t lbus_slaveA_hdr_cnt :4;
uint64_t lbus_slaveA_data_cnt :8;
uint64_t pib_slaveB_hdr_cnt :4;
uint64_t pib_slaveB_data_cnt :8;
uint64_t _reserved_0 :32;
#else
uint64_t _reserved_0 :32;
uint64_t lbus_slaveA_data_cnt :8;
uint64_t lbus_slaveA_hdr_cnt :4;
uint64_t pib_slaveB_data_cnt :8;
uint64_t pib_slaveB_hdr_cnt :4;
uint64_t _reserved_2 :1;
uint64_t xup :1;
uint64_t xdn :1;
uint64_t _reserved_1 :1;
uint64_t pib_slaveB_pending :1;
uint64_t lbus_slaveA_pending :1;
uint64_t abort :1;
uint64_t permission_to_send :1;
#endif
};
uint64_t doubleword;
};
} doorbl_stsctrl_reg_t;
/**
* @struct mbox_payload_t
* @brief Breakdown of the Mailbox1 Data, which OCC uses to alert TMGT.
* This is the actual data that TMGT can get from the mailbox
* when it is notified of an alert.
*/
typedef struct mbox_payload
{
/// This is the command type OCC uses to tell TMGT if this was a
/// Response Ready, or Service Required (eFspAlertType)
uint32_t type;
union
{
struct
{
/// Unused: 0 -> async, 1 -> sync.
uint32_t __reserved__async:1;
/// Unused: This is for internal hostboot use.
uint32_t __reserved__mbox_sync:1;
/// Unused
uint32_t __reserved__unused:30;
};
uint32_t flags;
};
union
{
struct
{
/// "Write" Buffer Address (from TMGT perspective)
uint32_t fsp_cmd_buffer_addr;
/// "Read" Buffer Address (from TMGT perspective)
uint32_t fsp_rsp_buffer_addr;
/// Unused
uint8_t _reserved[7];
/// Sanity check on OCC Id (should match up with HUID)
uint8_t occ_id;
};
uint64_t data[2];
};
/// If extra_data != NULL, data[1] is required to have size of extra_data (in bytes)
uint64_t extra_data;
} mbox_payload_t;
/**
* @struct mbox_msg_t
* @brief Breakdown of the Full Mailbox1, which OCC uses to alert TMGT.
* This is the actual data that HWSV gets from the PIB, which it
* then uses to notify TMGT of an alert, and sends TMGT the msg_payload
*/
typedef struct
{
/// Unused: Identifier assigned by originating endpoint for correlating
/// sync message responses.
uint32_t msg_id;
/// FSI2HOST Assigned Queue ID. 0x80000000 - 0xFFFFFFFF = FSP msg_queue,
/// 0x0 - 0x80000000 = Hostboot msg_queue. 0x80000007 = OCC
uint32_t msg_queue_id;
/// Message Payload (what TMGT gets)
mbox_payload_t msg_payload;
} mbox_msg_t;
/**
* @struct mbox_data_area_regs_t
* @brief Union of the Full Mailbox1, which OCC uses to alert TMGT.
* Since the data is SCOM'd, we want to parse it by uint64_t's
* to do the scom, and fill it out using the mbox_msg_t.
*/
typedef union
{
/// Parsed out fields the way OCC & TMGT interpret them
mbox_msg_t fields;
/// Words used in putscoms
uint64_t word[8];
} mbox_data_area_regs_t;
/*******************************************************************/
/* Globals */
/*******************************************************************/
extern eFsi2HostMboxState G_fsi2host_mbox_ready; // @th036
extern eCmdhWakeupThreadMask G_cmdh_thread_wakeup_mask; // @th039
extern fsp_cmd_t G_htmgt_cmd_buffer;
extern fsp_rsp_t G_htmgt_rsp_buffer;
/*******************************************************************/
/* Function Prototypes */
/*******************************************************************/
int cmdh_fsp_attention(uint32_t i_type);
int cmdh_fsp_attention_withRetry(uint32_t i_type, int i_timeout_in_ms); // @th039
void notifyCmdhWakeupCondition(eCmdhWakeupThreadMask i_cond); // @th039
void clearCmdhWakeupCondition(eCmdhWakeupThreadMask i_cond); // @th039
int cmdh_thread_wait_for_wakeup(void); // @th039
errlHndl_t cmdh_fsp_cmd_hndler(void);
errlHndl_t cmdh_fsp_init(void);
void cmdh_build_errl_rsp(const cmdh_fsp_cmd_t * i_cmd_ptr,
cmdh_fsp_rsp_t * o_rsp_ptr,
ERRL_RC i_rc,
errlHndl_t * io_errlHndl); // @th036
#endif
|