xref: /aosp_15_r20/external/coreboot/src/include/cpu/power/scom.h (revision b9411a12aaaa7e1e6a6fb7c5e057f44ee179a49c)
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 
3 #ifndef CPU_PPC64_SCOM_H
4 #define CPU_PPC64_SCOM_H
5 
6 #include <arch/byteorder.h>	// PPC_BIT(), PPC_BITMASK()
7 
8 // 32b SCOM address:
9 //
10 //      8         7         6         5         4         3         2         1
11 //
12 //  |       | |       | |    1 1| |1 1 1 1| |1 1 1 1| |2 2 2 2| |2 2 2 2| |2 2 3 3|
13 //  |0 1 2 3| |4 5 6 7| |8 9 0 1| |2 3 4 5| |6 7 8 9| |0 1 2 3| |4 5 6 7| |8 9 0 1|
14 //    {A}{     B      }           {   C   }     {    D    }{   E   }{      F      }
15 //
16 // A - Is multiCast if bit 1 = 0x1
17 // B - Contains Chiplet ID (6 bits) [2:7]
18 // C - Contains Port Number (4 bits) [12:15]
19 // D - Ring (4 bits) [18:21]
20 // E - Sat ID (4 bits) [22:25]
21 // F - Sat Offset (6 bits) [26:31]
22 //
23 // For 64b SCOM address all of the fields are shifted 32b to the right:
24 // A - Is multiCast if bit 33 = 0x1
25 // B - Contains Chiplet ID (6 bits) [34:39]
26 // C - Contains Port Number (4 bits) [44:47]
27 // D - Ring (4 bits) [50:53]
28 // E - Sat ID (4 bits) [54:57]
29 // F - Sat Offset (6 bits) [58:63]
30 // Higher bits specify indirect address
31 
32 #define XSCOM_ADDR_IND_FLAG		PPC_BIT(0)
33 
34 #ifndef __ASSEMBLER__
35 #include <types.h>
36 #include <arch/io.h>
37 
38 // TODO: these are probably specific to POWER9
39 typedef enum {
40 	PIB_CHIPLET_ID  = 0x00,     ///< PIB chiplet
41 	PERV_CHIPLET_ID = 0x01,     ///< TP chiplet
42 	N0_CHIPLET_ID   = 0x02,     ///< Nest0 (North) chiplet
43 	N1_CHIPLET_ID   = 0x03,     ///< Nest1 (East) chiplet
44 	N2_CHIPLET_ID   = 0x04,     ///< Nest2 (South) chiplet
45 	N3_CHIPLET_ID   = 0x05,     ///< Nest3 (West) chiplet
46 	XB_CHIPLET_ID   = 0x06,     ///< XBus chiplet
47 	MC01_CHIPLET_ID = 0x07,     ///< MC01 (West) chiplet
48 	MC23_CHIPLET_ID = 0x08,     ///< MC23 (East) chiplet
49 	OB0_CHIPLET_ID  = 0x09,     ///< OBus0 chiplet
50 	OB1_CHIPLET_ID  = 0x0A,     ///< OBus1 chiplet (Cumulus only)
51 	OB2_CHIPLET_ID  = 0x0B,     ///< OBus2 chiplet (Cumulus only)
52 	OB3_CHIPLET_ID  = 0x0C,     ///< OBus3 chiplet
53 	PCI0_CHIPLET_ID = 0x0D,     ///< PCIe0 chiplet
54 	PCI1_CHIPLET_ID = 0x0E,     ///< PCIe1 chiplet
55 	PCI2_CHIPLET_ID = 0x0F,     ///< PCIe2 chiplet
56 	EP00_CHIPLET_ID = 0x10,     ///< Quad0 chiplet (EX0/1)
57 	EP01_CHIPLET_ID = 0x11,     ///< Quad1 chiplet (EX2/3)
58 	EP02_CHIPLET_ID = 0x12,     ///< Quad2 chiplet (EX4/5)
59 	EP03_CHIPLET_ID = 0x13,     ///< Quad3 chiplet (EX6/7)
60 	EP04_CHIPLET_ID = 0x14,     ///< Quad4 chiplet (EX8/9)
61 	EP05_CHIPLET_ID = 0x15,     ///< Quad5 chiplet (EX10/11)
62 	EC00_CHIPLET_ID = 0x20,     ///< Core0 chiplet (Quad0, EX0, C0)
63 	EC01_CHIPLET_ID = 0x21,     ///< Core1 chiplet (Quad0, EX0, C1)
64 	EC02_CHIPLET_ID = 0x22,     ///< Core2 chiplet (Quad0, EX1, C0)
65 	EC03_CHIPLET_ID = 0x23,     ///< Core3 chiplet (Quad0, EX1, C1)
66 	EC04_CHIPLET_ID = 0x24,     ///< Core4 chiplet (Quad1, EX2, C0)
67 	EC05_CHIPLET_ID = 0x25,     ///< Core5 chiplet (Quad1, EX2, C1)
68 	EC06_CHIPLET_ID = 0x26,     ///< Core6 chiplet (Quad1, EX3, C0)
69 	EC07_CHIPLET_ID = 0x27,     ///< Core7 chiplet (Quad1, EX3, C1)
70 	EC08_CHIPLET_ID = 0x28,     ///< Core8 chiplet (Quad2, EX4, C0)
71 	EC09_CHIPLET_ID = 0x29,     ///< Core9 chiplet (Quad2, EX4, C1)
72 	EC10_CHIPLET_ID = 0x2A,     ///< Core10 chiplet (Quad2, EX5, C0)
73 	EC11_CHIPLET_ID = 0x2B,     ///< Core11 chiplet (Quad2, EX5, C1)
74 	EC12_CHIPLET_ID = 0x2C,     ///< Core12 chiplet (Quad3, EX6, C0)
75 	EC13_CHIPLET_ID = 0x2D,     ///< Core13 chiplet (Quad3, EX6, C1)
76 	EC14_CHIPLET_ID = 0x2E,     ///< Core14 chiplet (Quad3, EX7, C0)
77 	EC15_CHIPLET_ID = 0x2F,     ///< Core15 chiplet (Quad3, EX7, C1)
78 	EC16_CHIPLET_ID = 0x30,     ///< Core16 chiplet (Quad4, EX8, C0)
79 	EC17_CHIPLET_ID = 0x31,     ///< Core17 chiplet (Quad4, EX8, C1)
80 	EC18_CHIPLET_ID = 0x32,     ///< Core18 chiplet (Quad4, EX9, C0)
81 	EC19_CHIPLET_ID = 0x33,     ///< Core19 chiplet (Quad4, EX9, C1)
82 	EC20_CHIPLET_ID = 0x34,     ///< Core20 chiplet (Quad5, EX10, C0)
83 	EC21_CHIPLET_ID = 0x35,     ///< Core21 chiplet (Quad5, EX10, C1)
84 	EC22_CHIPLET_ID = 0x36,     ///< Core22 chiplet (Quad5, EX11, C0)
85 	EC23_CHIPLET_ID = 0x37      ///< Core23 chiplet (Quad5, EX11, C1)
86 } chiplet_id_t;
87 
88 uint64_t read_scom_direct(uint64_t reg_address);
89 void write_scom_direct(uint64_t reg_address, uint64_t data);
90 
91 uint64_t read_scom_indirect(uint64_t reg_address);
92 void write_scom_indirect(uint64_t reg_address, uint64_t data);
93 
write_scom(uint64_t addr,uint64_t data)94 static inline void write_scom(uint64_t addr, uint64_t data)
95 {
96 	if (addr & XSCOM_ADDR_IND_FLAG)
97 		write_scom_indirect(addr, data);
98 	else
99 		write_scom_direct(addr, data);
100 }
101 
read_scom(uint64_t addr)102 static inline uint64_t read_scom(uint64_t addr)
103 {
104 	if (addr & XSCOM_ADDR_IND_FLAG)
105 		return read_scom_indirect(addr);
106 	else
107 		return read_scom_direct(addr);
108 }
109 
scom_and_or(uint64_t addr,uint64_t and,uint64_t or)110 static inline void scom_and_or(uint64_t addr, uint64_t and, uint64_t or)
111 {
112 	uint64_t data = read_scom(addr);
113 	write_scom(addr, (data & and) | or);
114 }
115 
scom_and(uint64_t addr,uint64_t and)116 static inline void scom_and(uint64_t addr, uint64_t and)
117 {
118 	scom_and_or(addr, and, 0);
119 }
120 
scom_or(uint64_t addr,uint64_t or)121 static inline void scom_or(uint64_t addr, uint64_t or)
122 {
123 	scom_and_or(addr, ~0, or);
124 }
125 
write_scom_for_chiplet(chiplet_id_t chiplet,uint64_t addr,uint64_t data)126 static inline void write_scom_for_chiplet(chiplet_id_t chiplet, uint64_t addr, uint64_t data)
127 {
128 	addr &= ~PPC_BITMASK(34, 39);
129 	addr |= ((chiplet & 0x3F) << 24);
130 	write_scom(addr, data);
131 }
132 
read_scom_for_chiplet(chiplet_id_t chiplet,uint64_t addr)133 static inline uint64_t read_scom_for_chiplet(chiplet_id_t chiplet, uint64_t addr)
134 {
135 	addr &= ~PPC_BITMASK(34, 39);
136 	addr |= ((chiplet & 0x3F) << 24);
137 	return read_scom(addr);
138 }
139 
scom_and_or_for_chiplet(chiplet_id_t chiplet,uint64_t addr,uint64_t and,uint64_t or)140 static inline void scom_and_or_for_chiplet(chiplet_id_t chiplet, uint64_t addr,
141 					   uint64_t and, uint64_t or)
142 {
143 	uint64_t data = read_scom_for_chiplet(chiplet, addr);
144 	write_scom_for_chiplet(chiplet, addr, (data & and) | or);
145 }
146 
scom_and_for_chiplet(chiplet_id_t chiplet,uint64_t addr,uint64_t and)147 static inline void scom_and_for_chiplet(chiplet_id_t chiplet, uint64_t addr, uint64_t and)
148 {
149 	scom_and_or_for_chiplet(chiplet, addr, and, 0);
150 }
151 
scom_or_for_chiplet(chiplet_id_t chiplet,uint64_t addr,uint64_t or)152 static inline void scom_or_for_chiplet(chiplet_id_t chiplet, uint64_t addr, uint64_t or)
153 {
154 	scom_and_or_for_chiplet(chiplet, addr, ~0, or);
155 }
156 
157 #endif /* __ASSEMBLER__ */
158 #endif /* CPU_PPC64_SCOM_H */
159