aboutsummaryrefslogtreecommitdiff
path: root/include/fsp.h
blob: 7ea162db01467106e73b27950a1219117763cea0 (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
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
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
/* 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.
 */


/*
 * IBM System P FSP (Flexible Service Processor)
 */
#ifndef __FSP_H
#define __FSP_H

#include <skiboot.h>
#include <psi.h>

/* Current max number of FSPs
 * one primary and one secondary is all we support
 */
#define FSP_MAX			2

/* Command protocol.
 *
 * Commands have a byte class and a byte subcommand. With the exception
 * of some HMC related commands (class 0xe0) which we don't support,
 * only one outstanding command is allowed for a given class.
 *
 * Note: 0xCE and 0xCF fall into the same class, ie, only one of them can
 *       be outstanding.
 *
 * A command is outstanding until it has been acknowledged. This doesn't
 * imply a response, the response can come later.
 */

/* Protocol status error codes used by the protocol */
#define FSP_STATUS_SUCCESS		0x00	/* Command successful */
#define FSP_STATUS_MORE_DATA		0x02	/* Success, EOF not reached */
#define FSP_STATUS_DATA_INLINE		0x11	/* Data inline in mbox */
#define FSP_STATUS_INVALID_SUBCMD	0x20
#define FSP_STATUS_INVALID_MOD		0x21
#define FSP_STATUS_INVALID_DATA		0x22
#define FSP_STATUS_INVALID_DPOSTATE	0x23
#define FSP_STATUS_DMA_ERROR		0x24
#define FSP_STATUS_INVALID_CMD		0x2c
#define FSP_STATUS_SEQ_ERROR		0x2d
#define FSP_STATUS_BAD_STATE		0x2e
#define FSP_STATUS_NOT_SUPPORTED	0x2f
#define FSP_STATUS_FILE_TOO_LARGE	0x43
#define FSP_STATUS_FLASH_INPROGRESS	0x61
#define FSP_STATUS_FLASH_NOPROGRESS	0x62
#define FSP_STATUS_FLASH_INVALID_SIDE	0x63
#define FSP_STATUS_GENERIC_ERROR	0xfe
#define FSP_STATUS_EOF_ERROR		0x02
#define FSP_STATUS_DMA_ERROR		0x24
#define FSP_STATUS_BUSY			0x3e
#define FSP_STATUS_FLASH_BUSY		0x3f
#define FSP_STATUS_INVALID_SUBID	0x41
#define FSP_STATUS_LENGTH_ERROR		0x42
#define FSP_STAUS_INVALID_HMC_ID	0x51
#define FSP_STATUS_SPCN_ERROR		0xA8	/* SPCN error */
#define FSP_STATUS_INVALID_LC		0xC0	/* Invalid location code */
#define FSP_STATUS_ENCL_IND_RESET	0xC2	/* Enclosure Indicator cannot be reset */
#define FSP_STATUS_TOD_RESET		0xA9	/* TOD reset due to invalid state at POR */
#define FSP_STATUS_TOD_PERMANENT_ERROR	0xAF	/* Permanent error in TOD */
#define FSP_STATUS_I2C_TRANS_ERROR	0xE4	/* I2C device / transmission error */
#define FSP_STATUS_IND_PARTIAL_SUCCESS	0xE5	/* Indicator partial success */
#define FSP_STATUS_GENERIC_FAILURE	0xEF	/* Generic Failure in execution */

/*
 * FSP registers
 *
 * All of the below register definitions come from the FSP0 "Black Widow" spec
 * They are the same for FSP1 except they are presented big-endian vs
 * little-endian for FSP0 -- which used PCI
 * all regs are 4 bytes wide, and we read the larger data areas in 4 byte
 * granularity as well 
 *
 * there are actually two defined sets of MBX registers
 * MBX2 can't generate interrupts to the host and only MBX1 is currently 
 * used by firmware running on the FSP, so we're mostly ignoring MBX2
 */

/* Device Reset Control Register */
#define FSP_DRCR_REG			0x00
#define FSP_DRCR_CLR_REG		0x04

/* Bit masks for DRCR */
#define FSP_DRCR_CMD_VALID		PPC_BIT32(16)
#define FSP_DRCR_TERMINATE		PPC_BIT32(17)
#define FSP_DRCR_PREP_FOR_RESET		PPC_BIT32(23)
#define FSP_DRCR_CLEAR_DISR		PPC_BIT32(30)

/* DRCR commands need the CMD_VALID bit set */
#define FSP_PREP_FOR_RESET_CMD		(FSP_DRCR_CMD_VALID | \
						FSP_DRCR_PREP_FOR_RESET)
#define FSP_DRCR_ACK_MASK		(0xff << 8)

/* Device Immediate Status Register */
#define FSP_DISR_REG			0x08
#define FSP_DISR_CLR_REG		0x0C

/* Bit masks for DISR */
#define FSP_DISR_FSP_UNIT_CHECK		PPC_BIT32(16)
#define FSP_DISR_FSP_RUNTIME_TERM	PPC_BIT32(21)
#define FSP_DISR_FSP_RR_COMPLETE	PPC_BIT32(22)
#define FSP_DISR_FSP_FLASH_TERM		PPC_BIT32(23)
#define FSP_DISR_RUNTIME_STATE_SYNCD	PPC_BIT32(24)
#define FSP_DISR_DBG_IN_PROGRESS	PPC_BIT32(25)
#define FSP_DISR_FSP_IN_RR		PPC_BIT32(26)
#define FSP_DISR_FSP_REBOOT_IN_PROGRESS	PPC_BIT32(27)
#define FSP_DISR_CRIT_OP_IN_PROGRESS	PPC_BIT32(28)
#define FSP_DISR_STATUS_ACK_RXD		PPC_BIT32(31)

#define FSP_DISR_HIR_TRIGGER_MASK	(FSP_DISR_FSP_UNIT_CHECK | \
						FSP_DISR_FSP_RUNTIME_TERM | \
						FSP_DISR_FSP_FLASH_TERM)

/* The host version of the control register shares bits with the FSP's
 * control reg. Those bits are defined such that one side can set
 * a bit and the other side can clear it
 */
#define FSP_MBX1_HCTL_REG		0x080 /* AKA DSCR1 */
#define FSP_MBX1_FCTL_REG		0x090
#define FSP_MBX2_HCTL_REG		0x0a0 /* AKA DSCR2 */
#define FSP_MBX2_FCTL_REG		0x0b0

/* Bits in the control reg */
#define FSP_MBX_CTL_PTS			(1 << 31)
#define FSP_MBX_CTL_ABORT		(1 << 30)
#define FSP_MBX_CTL_SPPEND		(1 << 29)
#define FSP_MBX_CTL_HPEND		(1 << 28)
#define FSP_MBX_CTL_XDN			(1 << 26)
#define FSP_MBX_CTL_XUP			(1 << 25)
#define FSP_MBX_CTL_HCHOST_MASK		(0xf << 20)
#define FSP_MBX_CTL_HCHOST_SHIFT	20
#define FSP_MBX_CTL_DCHOST_MASK		(0xff << 12)
#define FSP_MBX_CTL_DCHOST_SHIFT	12
#define FSP_MBX_CTL_HCSP_MASK		(0xf << 8)
#define FSP_MBX_CTL_HCSP_SHIFT		8
#define FSP_MBX_CTL_DCSP_MASK		(0xff)
#define FSP_MBX_CTL_DCSP_SHIFT		0

/* Three header registers owned by the host */
#define FSP_MBX1_HHDR0_REG		0x84
#define FSP_MBX1_HHDR1_REG		0x88
#define FSP_MBX1_HHDR2_REG		0x8C
#define FSP_MBX2_HHDR0_REG		0xa4
#define FSP_MBX2_HHDR1_REG		0xa8
#define FSP_MBX2_HHDR2_REG		0xaC

/* SP Doorbell Error Status register */
#define FSP_SDES_REG			0xc0

/* Host Doorbell Error Status register */
#define FSP_HDES_REG			0xc4

/* Bit definitions for both SDES and HDES
 *
 * Notes:
 *
 * - CLR: is written to clear the status and always reads
 *   as 0. It can be used to detect an error state (a HB
 *   freeze will return all 1's)
 * - ILLEGAL: illegal operation such as host trying to write
 *   to an FSP only register etc...
 * - WFULL: set if host tried to write to the SP doorbell while
 *   the pending bit is still set
 * - REMPTY: tried to read while host pending bit not set
 * - PAR: SP RAM parity error
 */
#define FSP_DBERRSTAT_ILLEGAL1		(1 << 27)
#define FSP_DBERRSTAT_WFULL1		(1 << 26)
#define FSP_DBERRSTAT_REMPTY1		(1 << 25)
#define FSP_DBERRSTAT_PAR1		(1 << 24)
#define FSP_DBERRSTAT_CLR1		(1 << 16)
#define FSP_DBERRSTAT_ILLEGAL2		(1 << 11)
#define FSP_DBERRSTAT_WFULL2		(1 << 10)
#define FSP_DBERRSTAT_REMPTY2		(1 <<  9)
#define FSP_DBERRSTAT_PAR2		(1 <<  8)
#define FSP_DBERRSTAT_CLR2		(1 <<  0)

/* Host Doorbell Interrupt Register and mask
 *
 * Note that while HDIR has bits for MBX2, only
 * MBX1 can actually generate interrupts. Thus only the
 * MBX1 bits are implemented in the mask register.
 */
#define FSP_HDIR_REG			0xc8
#define FSP_HDIM_SET_REG		0xcc
#define FSP_HDIM_CLR_REG		0xd0
#define FSP_DBIRQ_ERROR2		(1 << 10)
#define FSP_DBIRQ_XUP2			(1 <<  9)
#define FSP_DBIRQ_HPEND2		(1 <<  8)
#define FSP_DBIRQ_ERROR1		(1 <<  2)
#define FSP_DBIRQ_XUP1			(1 <<  1)
#define FSP_DBIRQ_HPEND1		(1 <<  0)
#define FSP_DBIRQ_MBOX1			(FSP_DBIRQ_ERROR1 | FSP_DBIRQ_XUP1 | \
					 FSP_DBIRQ_HPEND1)
#define FSP_DBIRQ_MBOX2			(FSP_DBIRQ_ERROR2 | FSP_DBIRQ_XUP2 | \
					 FSP_DBIRQ_HPEND2)
#define FSP_DBIRQ_ALL			(FSP_DBIRQ_MBOX1 | FSP_DBIRQ_MBOX2)

/* Doorbell Interrupt Register (FSP internal interrupt latch
 * read-only on host side
 */
#define FSP_PDIR_REG			0xd4
/* And associated mask */
#define FSP_PDIM_SET_REG       		0xd8
#define FSP_PDIM_CLR_REG       		0xdc

/* Bits for the above */
#define FSP_PDIRQ_ABORT2		(1 << 7)
#define FSP_PDIRQ_ABORT1		(1 << 6)
#define FSP_PDIRQ_ERROR2		(1 << 5)
#define FSP_PDIRQ_ERROR1		(1 << 4)
#define FSP_PDIRQ_XDN2			(1 << 3)
#define FSP_PDIRQ_XDN1			(1 << 2)
#define FSP_PDIRQ_SPPEND2		(1 << 1)
#define FSP_PDIRQ_SPPEND1		(1 << 0)

/* FSP owned headers */
#define FSP_MBX1_FHDR0_REG		0x094
#define FSP_MBX1_FHDR1_REG		0x098
#define FSP_MBX1_FHDR2_REG		0x09C
#define FSP_MBX2_FHDR0_REG		0x0b4
#define FSP_MBX2_FHDR1_REG		0x0b8
#define FSP_MBX2_FHDR2_REG		0x0bC

/* Data areas, we can only write to host data, and read from FSP data
 *
 * Each area is 0x140 bytes long
 */
#define FSP_MBX1_HDATA_AREA		0x100
#define FSP_MBX1_FDATA_AREA		0x200
#define FSP_MBX2_HDATA_AREA		0x300
#define FSP_MBX2_FDATA_AREA		0x400

/* These are scratch registers */
#define FSP_SCRATCH0_REG		0xe0
#define FSP_SCRATCH1_REG		0xe4
#define FSP_SCRATCH2_REG		0xe8
#define FSP_SCRATCH3_REG		0xec

/* This is what the cmd_sub_mod will have for FSP_MCLASS_RR_EVENT */
#define FSP_RESET_START			0x1
#define FSP_RELOAD_COMPLETE		0x2

/*
 * Message classes
 */

/* The FSP_MCLASS_RR_EVENT is a special message class that doesn't
 * participate in mbox event related activities. Its relevant only
 * for hypervisor internal use. So, handle it specially for command
 * class extraction too.
 */
#define FSP_MCLASS_RR_EVENT		0xaa	/* see FSP_R/R defines above */
#define FSP_MCLASS_FIRST		0xce
#define FSP_MCLASS_SERVICE		0xce
#define FSP_MCLASS_IPL			0xcf
#define FSP_MCLASS_PCTRL_MSG		0xd0
#define FSP_MCLASS_PCTRL_ABORTS		0xd1
#define FSP_MCLASS_ERR_LOG		0xd2
#define FSP_MCLASS_CODE_UPDATE		0xd3
#define FSP_MCLASS_FETCH_SPDATA		0xd4
#define FSP_MCLASS_FETCH_HVDATA		0xd5
#define FSP_MCLASS_NVRAM		0xd6
#define FSP_MCLASS_MBOX_SURV		0xd7
#define FSP_MCLASS_RTC			0xd8
#define FSP_MCLASS_SMART_CHIP		0xd9
#define FSP_MCLASS_INDICATOR		0xda
#define FSP_MCLASS_HMC_INTFMSG		0xe0
#define FSP_MCLASS_HMC_VT		0xe1
#define FSP_MCLASS_HMC_BUFFERS		0xe2
#define FSP_MCLASS_SHARK		0xe3
#define FSP_MCLASS_MEMORY_ERR		0xe4
#define FSP_MCLASS_CUOD_EVENT		0xe5
#define FSP_MCLASS_HW_MAINT		0xe6
#define FSP_MCLASS_VIO			0xe7
#define FSP_MCLASS_SRC_MSG		0xe8
#define FSP_MCLASS_DATA_COPY		0xe9
#define FSP_MCLASS_TONE			0xea
#define FSP_MCLASS_VIRTUAL_NVRAM	0xeb
#define FSP_MCLASS_TORRENT		0xec
#define FSP_MCLASS_NODE_PDOWN		0xed
#define FSP_MCLASS_DIAG			0xee
#define FSP_MCLASS_PCIE_LINK_TOPO	0xef
#define FSP_MCLASS_OCC			0xf0
#define FSP_MCLASS_LAST			0xf0

/*
 * Commands are provided in rxxyyzz form where:
 *
 *   -  r is 0: no response or 1: response expected
 *   - xx is class
 *   - yy is subcommand
 *   - zz is mod
 *
 * WARNING: We only set the r bit for HV->FSP commands
 *          long run, we want to remove use of that bit
 *          and instead have a table of all commands in
 *          the FSP driver indicating which ones take a
 *          response...
 */

/*
 * Class 0xCF
 */
#define FSP_CMD_OPL	    	0x0cf7100 /* HV->FSP: Operational Load Compl. */
#define FSP_CMD_HV_STATE_CHG	0x0cf0200 /* FSP->HV: Request HV state change */
#define FSP_RSP_HV_STATE_CHG	0x0cf8200
#define FSP_CMD_SP_NEW_ROLE	0x0cf0700 /* FSP->HV: FSP assuming a new role */
#define FSP_RSP_SP_NEW_ROLE	0x0cf8700
#define FSP_CMD_SP_RELOAD_COMP	0x0cf0102 /* FSP->HV: FSP reload complete */


/*
 * Class 0xCE
 */
#define FSP_CMD_ACK_DUMP	0x1ce0200 /* HV->FSP: Dump ack */
#define FSP_CMD_HV_QUERY_CAPS	0x1ce0400 /* HV->FSP: Query capabilities */
#define FSP_RSP_HV_QUERY_CAPS	0x1ce8400
#define FSP_CMD_SP_QUERY_CAPS	0x0ce0501 /* FSP->HV */
#define FSP_RSP_SP_QUERY_CAPS	0x0ce8500
#define FSP_CMD_GET_IPL_SIDE	0x1ce0600 /* HV->FSP: Get IPL side and speed */
#define FSP_CMD_SET_IPL_SIDE	0x1ce0780 /* HV->FSP: Set next IPL side */
#define FSP_CMD_ERRLOG_PHYP_ACK	0x1ce0800 /* HV->FSP */
#define FSP_RSP_ERRLOG_PHYP_ACK	0x0ce8800 /* FSP->HV */
#define FSP_CMD_ERRLOG_GET_PLID	0x0ce0900 /* FSP->HV: Get PLID */
#define FSP_RSP_ERRLOG_GET_PLID	0x0ce8900 /* HV->FSP */
#define FSP_CMD_SA_INDICATOR	0x1ce1000 /* HV->FSP: read/update SAI */
#define FSP_RSP_SA_INDICATOR	0x0ce9000 /* FSP->HV */
#define FSP_CMD_QUERY_SPARM	0x1ce1200 /* HV->FSP: System parameter query */
#define FSP_RSP_QUERY_SPARM	0x0ce9200 /* FSP->HV: System parameter resp */
#define FSP_CMD_SET_SPARM_1	0x1ce1301 /* HV->FSP: Set system parameter */
#define FSP_CMD_SET_SPARM_2	0x1ce1302 /* HV->FSP: Set system parameter TCE */
#define FSP_RSP_SET_SPARM	0x0ce9300 /* FSP->HV: Set system parameter resp */
#define FSP_CMD_SP_SPARM_UPD_0	0x0ce1600 /* FSP->HV: Sysparm updated no data */
#define FSP_CMD_SP_SPARM_UPD_1	0x0ce1601 /* FSP->HV: Sysparm updated data */
#define FSP_CMD_HYP_MDST_TABLE	0x1ce2600 /* HV->FSP: Sapphire MDST table */
#define FSP_CMD_TPO_READ	0x1ce4201 /* FSP->HV */
#define FSP_CMD_TPO_WRITE	0x1ce4301 /* HV->FSP */
#define FSP_CMD_STATUS_REQ	0x1ce4800 /* HV->FSP: Request normal panel status */
#define FSP_CMD_STATUS_EX1_REQ	0x1ce4802 /* HV->FSP: Request extended 1 panel status */
#define FSP_CMD_STATUS_EX2_REQ	0x1ce4803 /* HV->FSP: Request extended 2 panel status */
#define FSP_CMD_CONTINUE_ACK	0x0ce5700 /* HV->FSP: HV acks CONTINUE IPL */
#define FSP_CMD_HV_FUNCTNAL	0x1ce5707 /* HV->FSP: Set HV functional state */
#define FSP_CMD_FSP_FUNCTNAL	0x0ce5708 /* FSP->HV: FSP functional state */
#define FSP_CMD_CONTINUE_IPL	0x0ce7000 /* FSP->HV: HV has control */
#define FSP_RSP_SYS_DUMP_OLD	0x0ce7800 /* FSP->HV: Sys Dump Available */
#define FSP_RSP_SYS_DUMP	0x0ce7802 /* FSP->HV: Sys Dump Available */
#define FSP_RSP_RES_DUMP	0x0ce7807 /* FSP->HV: Resource Dump Available */
#define FSP_CMD_PCI_POWER_CONF	0x1ce1b00 /* HV->FSP: Send PCIe list to FSP */
#define FSP_CMD_POWERDOWN_NORM	0x1ce4d00 /* HV->FSP: Normal power down */
#define FSP_CMD_POWERDOWN_QUICK	0x1ce4d01 /* HV->FSP: Quick power down */
#define FSP_CMD_POWERDOWN_PCIRS	0x1ce4d02 /* HV->FSP: PCI cfg reset power dwn */
#define FSP_CMD_REBOOT		0x1ce4e00 /* HV->FSP: Standard IPL */
#define FSP_CMD_DEEP_REBOOT	0x1ce4e04 /* HV->FSP: Deep IPL */
#define FSP_CMD_INIT_DPO	0x0ce5b00 /* FSP->HV: Initialize Delayed Power Off */
#define FSP_RSP_INIT_DPO	0x0cedb00 /* HV->FSP: Response for DPO init command */
#define FSP_CMD_PANELSTATUS	0x0ce5c00 /* FSP->HV */
#define FSP_CMD_PANELSTATUS_EX1	0x0ce5c02 /* FSP->HV */
#define FSP_CMD_PANELSTATUS_EX2	0x0ce5c03 /* FSP->HV */

/* SAI read/update sub commands */
#define FSP_LED_RESET_REAL_SAI		0x00
#define FSP_LED_READ_REAL_SAI		0x02
#define FSP_LED_RESET_PARTITION_SAI	0x80
#define FSP_LED_SET_PARTITION_SAI	0x81
#define FSP_LED_READ_PARTITION_SAI	0x82
#define FSP_LED_READ_PLAT_SAI		0x83
#define FSP_LED_RESET_PLAT_SAI		0x84
#define FSP_LED_SET_PLAT_SAI		0x85

/*
 * Class 0xD2
 */
#define FSP_CMD_CREATE_ERRLOG		0x1d21000 /* HV->FSP */
#define FSP_RSP_CREATE_ERRLOG		0x0d29000 /* FSP->HV */
#define FSP_CMD_ERRLOG_NOTIFICATION	0x0d25a00 /* FSP->HV */
#define FSP_RSP_ERRLOG_NOTIFICATION	0x0d2da00 /* HV->FSP */
#define FSP_RSP_ELOG_NOTIFICATION_ERROR	0x1d2dafe /* HV->FSP */
#define FSP_CMD_FSP_DUMP_INIT		0x1d21200 /* HV->FSP: FSP dump init */

/*
 * Class 0xD0
 */
#define FSP_CMD_SPCN_PASSTHRU   0x1d05400 /* HV->FSP */
#define FSP_RSP_SPCN_PASSTHRU   0x0d0d400 /* FSP->HV */

/*
 * Class 0xD3
 */
#define FSP_CMD_FLASH_START	0x01d30101 /* HV->FSP: Code update start */
#define FSP_CMD_FLASH_COMPLETE	0x01d30201 /* HV->FSP: Code update complete */
#define FSP_CMD_FLASH_ABORT	0x01d302ff /* HV->FSP: Code update complete */
#define FSP_CMD_FLASH_WRITE	0x01d30300 /* HV->FSP: Write LID */
#define FSP_CMD_FLASH_DEL	0x01d30500 /* HV->FSP: Delete LID */
#define FSP_CMD_FLASH_NORMAL	0x01d30401 /* HV->FSP: Commit (T -> P) */
#define FSP_CMD_FLASH_REMOVE	0x01d30402 /* HV->FSP: Reject (P -> T) */
#define FSP_CMD_FLASH_SWAP	0x01d30403 /* HV->FSP: Swap */
#define FSP_CMD_FLASH_OUTC	0x00d30601 /* FSP->HV: Out of band commit */
#define FSP_CMD_FLASH_OUTR	0x00d30602 /* FSP->HV: Out of band reject */
#define FSP_CMD_FLASH_OUTS	0x00d30603 /* FSP->HV: Out of band swap */
#define FSP_CMD_FLASH_OUT_RSP	0x00d38600 /* HV->FSP: Out of band Resp */
#define FSP_CMD_FLASH_CACHE	0x00d30700 /* FSP->HV: Update LID cache */
#define FSP_CMD_FLASH_CACHE_RSP	0x00d38700 /* HV->FSP: Update LID cache Resp */

/*
 * Class 0xD4
 */
#define FSP_CMD_FETCH_SP_DATA	0x1d40101 /* HV->FSP: Fetch & DMA data */
#define FSP_CMD_WRITE_SP_DATA	0x1d40201 /* HV->FSP: Fetch & DMA data */
#define FSP_CMD_FETCH_PLAT_DATA	0x1d40500 /* HV->FSP: Platform function data */
#define FSP_CMD_SEND_PLAT_DATA	0x0d40501 /* FSP->HV */
#define FSP_RSP_PLAT_DATA	0x0d48500 /* HV->FSP */

/* Data set IDs for SP data commands */
#define FSP_DATASET_SP_DUMP	0x01
#define FSP_DATASET_HW_DUMP	0x02
#define FSP_DATASET_ERRLOG	0x03	/* error log entry */
#define FSP_DATASET_MASTER_LID	0x04
#define FSP_DATASET_NONSP_LID	0x05
#define FSP_DATASET_ELID_RDATA	0x06
#define FSP_DATASET_BLADE_PARM	0x07
#define FSP_DATASET_LOC_PORTMAP	0x08
#define FSP_DATASET_SYSIND_CAP	0x09
#define FSP_DATASET_FSP_RSRCDMP	0x0a
#define FSP_DATASET_HBRT_BLOB	0x0b

/* Adjustment to get T side LIDs */
#define ADJUST_T_SIDE_LID_NO	0x8000

/*
 * Class 0xD5
 */
#define FSP_CMD_ALLOC_INBOUND	0x0d50400 /* FSP->HV: Allocate inbound buf. */
#define FSP_RSP_ALLOC_INBOUND	0x0d58400

/*
 * Class 0xD7
 */
#define FSP_CMD_SURV_HBEAT	0x1d70000 /* ? */
#define FSP_CMD_SURV_ACK	0x0d78000 /* ? */

/*
 * Class 0xD8
 */
#define FSP_CMD_READ_TOD	0x1d82000 /* HV->FSP */
#define FSP_CMD_READ_TOD_EXT	0x1d82001 /* HV->FSP */
#define FSP_CMD_WRITE_TOD	0x1d82100 /* HV->FSP */
#define FSP_CMD_WRITE_TOD_EXT	0x1d82101 /* HV->FSP */

/*
 * Class 0xDA
 */
#define FSP_CMD_GET_LED_LIST   0x00da1101 /* Location code information structure */
#define FSP_RSP_GET_LED_LIST   0x00da9100
#define FSP_CMD_RET_LED_BUFFER 0x00da1102 /* Location code buffer information */
#define FSP_RSP_RET_LED_BUFFER 0x00da9100
#define FSP_CMD_GET_LED_STATE  0x00da1103 /* Retrieve Indicator State */
#define FSP_RSP_GET_LED_STATE  0x00da9100
#define FSP_CMD_SET_LED_STATE  0x00da1104 /* Set Service Indicator State */
#define FSP_RSP_SET_LED_STATE  0x00da9100
#define FSP_CMD_GET_MTMS_LIST  0x00da1105 /* Get MTMS and config ID list */
#define FSP_RSP_GET_MTMS_LIST  0x00da9100
#define FSP_CMD_SET_ENCL_MTMS  0x00da1106 /* Set MTMS */
#define FSP_RSP_SET_ENCL_MTMS  0x00da9100
#define FSP_CMD_SET_ENCL_CNFG  0x00da1107 /* Set config ID */
#define FSP_RSP_SET_ENCL_CNFG  0x00da9100
#define FSP_CMD_CLR_INCT_ENCL  0x00da1108 /* Clear inactive address */
#define FSP_RSP_CLR_INCT_ENCL  0x00da9100
#define FSP_CMD_RET_MTMS_BUFFER  0x00da1109 /* Return MTMS buffer */
#define FSP_RSP_RET_MTMS_BUFFER  0x00da9100
#define FSP_CMD_ENCL_MCODE_INIT  0x00da110A /* Mcode update (Initiate download) */
#define FSP_RSP_ENCL_MCODE_INIT  0x00da9100
#define FSP_CMD_ENCL_MCODE_INTR  0x00da110B /* Mcode update (Interrupt download) */
#define FSP_RSP_ENCL_MCODE_INTR  0x00da9100
#define FSP_CMD_ENCL_POWR_TRACE  0x00da110D /* Enclosure power network trace */
#define FSP_RSP_ENCL_POWR_TRACE  0x00da9100
#define FSP_CMD_RET_ENCL_TRACE_BUFFER  0x00da110E /* Return power trace buffer */
#define FSP_RSP_RET_ENCL_TRACE_BUFFER  0x00da9100
#define FSP_CMD_GET_SPCN_LOOP_STATUS   0x00da110F /* Get SPCN loop status */
#define FSP_RSP_GET_SPCN_LOOP_STATUS   0x00da9100
#define FSP_CMD_INITIATE_LAMP_TEST     0x00da1300 /* Initiate LAMP test */

/*
 * Class 0xE0
 *
 * HACK ALERT: We mark E00A01 (associate serial port) as not needing
 * a response. We need to do that because the FSP will send as a result
 * an Open Virtual Serial of the same class *and* expect a reply before
 * it will respond to associate serial port. That breaks our logic of
 * supporting only one cmd/resp outstanding per class.
 */
#define FSP_CMD_HMC_INTF_QUERY	0x0e00100 /* FSP->HV */
#define FSP_RSP_HMC_INTF_QUERY	0x0e08100 /* HV->FSP */
#define FSP_CMD_ASSOC_SERIAL	0x0e00a01 /* HV->FSP: Associate with a port */
#define FSP_RSP_ASSOC_SERIAL	0x0e08a00 /* FSP->HV */
#define FSP_CMD_UNASSOC_SERIAL	0x0e00b01 /* HV->FSP: Deassociate */
#define FSP_RSP_UNASSOC_SERIAL	0x0e08b00 /* FSP->HV */
#define FSP_CMD_OPEN_VSERIAL	0x0e00601 /* FSP->HV: Open serial session */
#define FSP_RSP_OPEN_VSERIAL	0x0e08600 /* HV->FSP */
#define FSP_CMD_CLOSE_VSERIAL	0x0e00701 /* FSP->HV: Close serial session */
#define FSP_RSP_CLOSE_VSERIAL	0x0e08700 /* HV->FSP */
#define FSP_CMD_CLOSE_HMC_INTF	0x0e00300 /* FSP->HV: Close HMC interface */
#define FSP_RSP_CLOSE_HMC_INTF	0x0e08300 /* HV->FSP */

/*
 * Class E1
 */
#define FSP_CMD_VSERIAL_IN	0x0e10100 /* FSP->HV */
#define FSP_CMD_VSERIAL_OUT	0x0e10200 /* HV->FSP */

/*
 * Class E6
 */
#define FSP_CMD_TOPO_ENABLE_DISABLE	0x0e60600 /* FSP->HV */
#define FSP_RSP_TOPO_ENABLE_DISABLE	0x0e68600 /* HV->FSP */

/*
 * Class E8
 */
#define FSP_CMD_READ_SRC	0x1e84a40 /* HV->FSP */
#define FSP_CMD_DISP_SRC_INDIR	0x1e84a41 /* HV->FSP */
#define FSP_CMD_DISP_SRC_DIRECT	0x1e84a42 /* HV->FSP */
#define FSP_CMD_CLEAR_SRC	0x1e84b00 /* HV->FSP */
#define FSP_CMD_DIS_SRC_ECHO	0x1e87600 /* HV->FSP */

/*
 * Class EB
 */
#define FSP_CMD_GET_VNVRAM_SIZE	0x01eb0100 /* HV->FSP */
#define FSP_CMD_OPEN_VNVRAM	0x01eb0200 /* HV->FSP */
#define FSP_CMD_READ_VNVRAM	0x01eb0300 /* HV->FSP */
#define FSP_CMD_WRITE_VNVRAM	0x01eb0400 /* HV->FSP */
#define FSP_CMD_GET_VNV_STATS	0x00eb0500 /* FSP->HV */
#define FSP_RSP_GET_VNV_STATS	0x00eb8500
#define FSP_CMD_FREE_VNV_STATS	0x00eb0600 /* FSP->HV */
#define FSP_RSP_FREE_VNV_STATS	0x00eb8600

/*
 * Class 0xEE
 */
#define FSP_RSP_DIAG_LINK_ERROR  0x00ee1100 /* FSP->HV */
#define FSP_RSP_DIAG_ACK_TIMEOUT 0x00ee0000 /* FSP->HV */

/*
 * Class F0
 */
#define FSP_CMD_LOAD_OCC	0x00f00100 /* FSP->HV */
#define FSP_RSP_LOAD_OCC	0x00f08100 /* HV->FSP */
#define FSP_CMD_LOAD_OCC_STAT	0x01f00300 /* HV->FSP */
#define FSP_CMD_RESET_OCC	0x00f00200 /* FSP->HV */
#define FSP_RSP_RESET_OCC	0x00f08200 /* HV->FSP */
#define FSP_CMD_RESET_OCC_STAT	0x01f00400 /* HV->FSP */

/*
 * Class E4
 */
#define FSP_CMD_MEM_RES_CE	0x00e40300 /* FSP->HV: Memory resilience CE */
#define FSP_CMD_MEM_RES_UE	0x00e40301 /* FSP->HV: Memory resilience UE */
#define FSP_CMD_MEM_RES_UE_SCRB	0x00e40302 /* FSP->HV: UE detected by scrub */
#define FSP_RSP_MEM_RES		0x00e48300 /* HV->FSP */
#define FSP_CMD_MEM_DYN_DEALLOC	0x00e40500 /* FSP->HV: Dynamic mem dealloc */
#define FSP_RSP_MEM_DYN_DEALLOC	0x00e48500 /* HV->FSP */

/*
 * Functions exposed to the rest of skiboot
 */

/* An FSP message */

enum fsp_msg_state {
	fsp_msg_unused = 0,
	fsp_msg_queued,
	fsp_msg_sent,
	fsp_msg_wresp,
	fsp_msg_done,
	fsp_msg_timeout,
	fsp_msg_incoming,
	fsp_msg_response,
	fsp_msg_cancelled,
};

struct fsp_msg {
	/*
	 * User fields. Don't populate word0.seq (upper 16 bits), this
	 * will be done by fsp_queue_msg()
	 */
	u8			dlen;	/* not including word0/word1 */
	u32			word0;	/* seq << 16 | cmd */
	u32			word1;	/* mod << 8 | sub */
	union {
		u32		words[14];
		u8		bytes[56];
	} data;

	/* Completion function. Called with no lock held */
	void (*complete)(struct fsp_msg *msg);
	void *user_data;

	/*
	 * Driver updated fields
	 */

	/* Current msg state */
	enum fsp_msg_state	state;

	/* Set if the message expects a response */
	bool			response;

	/* Response will be filed by driver when response received */
	struct fsp_msg		*resp;

	/* Internal queuing */
	struct list_node	link;
};

/* This checks if a message is still "in progress" in the FSP driver */
static inline bool fsp_msg_busy(struct fsp_msg *msg)
{
	switch(msg->state) {
	case fsp_msg_unused:
	case fsp_msg_done:
	case fsp_msg_timeout:
	case fsp_msg_response: /* A response is considered a completed msg */
		return false;
	default:
		break;
	}
	return true;
}

static inline u32 fsp_msg_cmd(const struct fsp_msg *msg)
{
	u32 cmd_sub_mod;
	cmd_sub_mod = (msg->word0 & 0xff) << 16;
	cmd_sub_mod |= (msg->word1 & 0xff) << 8;
	cmd_sub_mod |= (msg->word1 & 0xff00) >> 8;
	return cmd_sub_mod;
}

/* Initialize the FSP mailbox driver */
extern void fsp_init(void);

/* Perform the OPL sequence */
extern void fsp_opl(void);

/* Check if system has an FSP */
extern bool fsp_present(void);

/* Allocate and populate an fsp_msg structure
 *
 * WARNING: Do _NOT_ use free() on an fsp_msg, use fsp_freemsg()
 * instead as we will eventually use pre-allocated message pools
 */
extern struct fsp_msg *fsp_allocmsg(bool alloc_response) __warn_unused_result;
extern struct fsp_msg *fsp_mkmsg(u32 cmd_sub_mod, u8 add_words, ...) __warn_unused_result;

/* Populate a pre-allocated msg */
extern void fsp_fillmsg(struct fsp_msg *msg, u32 cmd_sub_mod, u8 add_words, ...);

/* Free a message
 *
 * WARNING: This will also free an attached response if any
 */
extern void fsp_freemsg(struct fsp_msg *msg);

/* Free a message and not the attached reply */
extern void __fsp_freemsg(struct fsp_msg *msg);

/* Cancel a message from the msg queue
 *
 * WARNING: * This is intended for use only in the FSP r/r scenario.
 * 	    * This will also free an attached response if any
 */
extern void fsp_cancelmsg(struct fsp_msg *msg);

/* Enqueue it in the appropriate FSP queue
 *
 * NOTE: This supports being called with the FSP lock already
 * held. This is the only function in this module that does so
 * and is meant to be used that way for sending serial "poke"
 * commands to the FSP.
 */
extern int fsp_queue_msg(struct fsp_msg *msg,
			 void (*comp)(struct fsp_msg *msg)) __warn_unused_result;

/* Synchronously send a command. If there's a response, the status is
 * returned as a positive number. A negative result means an error
 * sending the message.
 *
 * If autofree is set, the message and the reply (if any) are freed
 * after extracting the status. If not set, you are responsible for
 * freeing both the message and an eventual response
 *
 * NOTE: This will call fsp_queue_msg(msg, NULL), hence clearing the
 * completion field of the message. No synchronous message is expected
 * to utilize asynchronous completions.
 */
extern int fsp_sync_msg(struct fsp_msg *msg, bool autofree);

/* Handle FSP interrupts */
extern void fsp_interrupt(void);

/* An FSP client is interested in messages for a given class */
struct fsp_client {
	/* Return true to "own" the message (you can free it) */
	bool	(*message)(u32 cmd_sub_mod, struct fsp_msg *msg);
	struct list_node	link;
};

/* WARNING: Command class FSP_MCLASS_IPL is aliased to FSP_MCLASS_SERVICE,
 * thus a client of one will get both types of messages.
 *
 * WARNING: Client register/unregister takes *NO* lock. These are expected
 * to be called early at boot before CPUs are brought up and before
 * fsp_poll() can race. The client callback is called with no lock held.
 */
extern void fsp_register_client(struct fsp_client *client, u8 msgclass);
extern void fsp_unregister_client(struct fsp_client *client, u8 msgclass);

/* FSP TCE map/unmap functions */
extern void fsp_tce_map(u32 offset, void *addr, u32 size);
extern void fsp_tce_unmap(u32 offset, u32 size);
extern void *fsp_inbound_buf_from_tce(u32 tce_token);

/* Data fetch helper */
extern uint32_t fsp_adjust_lid_side(uint32_t lid_no);
extern int fsp_fetch_data(uint8_t flags, uint16_t id, uint32_t sub_id,
			  uint32_t offset, void *buffer, size_t *length);
extern int fsp_fetch_data_queue(uint8_t flags, uint16_t id, uint32_t sub_id,
				uint32_t offset, void *buffer, size_t *length,
				void (*comp)(struct fsp_msg *msg)) __warn_unused_result;
extern int fsp_start_preload_resource(enum resource_id id, uint32_t idx,
				      void *buf, size_t *size);
extern int fsp_resource_loaded(enum resource_id id, uint32_t idx);
extern int fsp_preload_lid(uint32_t lid_no, char *buf, size_t *size);
extern int fsp_wait_lid_loaded(uint32_t lid_no);

/* FSP console stuff */
extern void fsp_console_preinit(void);
extern void fsp_console_init(void);
extern void fsp_console_add_nodes(void);
extern void fsp_console_select_stdout(void);
extern void fsp_console_reset(void);
extern void fsp_console_poll(void *);

/* Mark FSP lock */
extern void fsp_used_by_console(void);

/* NVRAM */
extern int fsp_nvram_info(uint32_t *total_size);
extern int fsp_nvram_start_read(void *dst, uint32_t src, uint32_t len);
extern int fsp_nvram_write(uint32_t offset, void *src, uint32_t size);
extern void fsp_nvram_wait_open(void);

/* RTC */
extern void fsp_rtc_init(void);

/* ELOG */
extern void fsp_elog_read_init(void);
extern void fsp_elog_write_init(void);

/* Code update */
extern void fsp_code_update_init(void);
extern void fsp_code_update_wait_vpd(bool is_boot);

/* Dump */
extern void fsp_dump_init(void);
extern void fsp_fips_dump_notify(uint32_t dump_id, uint32_t dump_len);

/* Attention Handler */
extern void fsp_attn_init(void);

/* MDST table */
extern void fsp_mdst_table_init(void);

/* This can be set by the fsp_opal_update_flash so that it can
 * get called just reboot we reboot shutdown the machine.
 */
extern int (*fsp_flash_term_hook)(void);

/* Surveillance */
extern void fsp_init_surveillance(void);
extern void fsp_surv_query(void);

/* IPMI */
extern void fsp_ipmi_init(void);

/* Reset/Reload */
extern void fsp_reinit_fsp(void);
extern void fsp_trigger_reset(void);
extern void fsp_reset_links(void);

/* FSP memory errors */
extern void fsp_memory_err_init(void);

/* Sensor */
extern void fsp_init_sensor(void);
extern int64_t fsp_opal_read_sensor(uint32_t sensor_hndl, int token,
			uint32_t *sensor_data);

/* Diagnostic */
extern void fsp_init_diag(void);

/* LED */
extern void fsp_led_init(void);
extern void create_led_device_nodes(void);

/* EPOW */
extern void fsp_epow_init(void);

/* DPO */
extern void fsp_dpo_init(void);
extern bool fsp_dpo_pending;

/* Chiptod */
extern void fsp_chiptod_init(void);

/* Terminate immediate */
extern void __attribute__((noreturn)) ibm_fsp_terminate(const char *msg);

#endif /* __FSP_H */