Skip to content

Commit 7d41d05

Browse files
author
Igor Bagnucki
committed
Add OCC operations
Signed-off-by: Igor Bagnucki <[email protected]>
1 parent a6a261b commit 7d41d05

File tree

3 files changed

+196
-0
lines changed

3 files changed

+196
-0
lines changed

src/include/cpu/power/occ.h

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
/* SPDX-License-Identifier: GPL-2.0-only */
2+
3+
#ifndef CPU_PPC64_OCC_H
4+
#define CPU_PPC64_OCC_H
5+
6+
#include <cpu/power/scom.h>
7+
8+
#define OCC_405_SRAM_ADDRESS (0xFFF40000)
9+
#define OCC_OFFSET_MAIN_EP (0x6C)
10+
#define OCC_BRANCH_INSTR (0x4B00000200000000)
11+
#define BRANCH_ADDR_MASK (0x00FFFFFC)
12+
13+
#define OCB_PIB_OCBCSR0_OCB_STREAM_MODE (4)
14+
#define OCB_PIB_OCBCSR0_OCB_STREAM_TYPE (5)
15+
16+
#define OCB_OCI_OCBSHCS0_PUSH_ENABLE (31)
17+
#define OCB_OCI_OCBSHCS0_PUSH_FULL (0)
18+
19+
#define PU_OCB_PIB_OCBCSR0_RO (0x0006D011)
20+
#define PU_OCB_OCI_OCBSHCS0_SCOM (0x0006C204)
21+
#define PU_OCB_PIB_OCBDR0 (0x0006D015)
22+
23+
#define PU_OCB_PIB_OCBCSR0_OR (0x0006D013)
24+
#define PU_OCB_PIB_OCBCSR1_OR (0x0006D033)
25+
#define PU_OCB_PIB_OCBCSR2_OR (0x0006D053)
26+
#define PU_OCB_PIB_OCBCSR3_OR (0x0006D073)
27+
28+
#define PU_OCB_PIB_OCBCSR0_CLEAR (0x0006D012)
29+
#define PU_OCB_PIB_OCBCSR1_CLEAR (0x0006D032)
30+
#define PU_OCB_PIB_OCBCSR2_CLEAR (0x0006D052)
31+
#define PU_OCB_PIB_OCBCSR3_CLEAR (0x0006D072)
32+
33+
#define PU_OCB_PIB_OCBAR0 (0x0006D010)
34+
#define PU_OCB_PIB_OCBAR1 (0x0006D030)
35+
#define PU_OCB_PIB_OCBAR2 (0x0006D050)
36+
#define PU_OCB_PIB_OCBAR3 (0x0006D070)
37+
38+
#define EX_PPM_SPWKUP_OCC (0x200F010C)
39+
40+
#define NUMBER_OF_EX_CHIPLETS (6)
41+
const chiplet_id_t EX_CHIPLETS[NUMBER_OF_EX_CHIPLETS] =
42+
{
43+
EP00_CHIPLET_ID,
44+
EP01_CHIPLET_ID,
45+
EP02_CHIPLET_ID,
46+
EP03_CHIPLET_ID,
47+
EP04_CHIPLET_ID,
48+
EP05_CHIPLET_ID
49+
};
50+
51+
const uint64_t OCBARn[4] =
52+
{
53+
PU_OCB_PIB_OCBAR0,
54+
PU_OCB_PIB_OCBAR1,
55+
PU_OCB_PIB_OCBAR2,
56+
PU_OCB_PIB_OCBAR3
57+
};
58+
59+
const uint64_t OCBCSRn_CLEAR[4] =
60+
{
61+
PU_OCB_PIB_OCBCSR0_CLEAR,
62+
PU_OCB_PIB_OCBCSR1_CLEAR,
63+
PU_OCB_PIB_OCBCSR2_CLEAR,
64+
PU_OCB_PIB_OCBCSR3_CLEAR
65+
};
66+
67+
const uint64_t OCBCSRn_OR[4] =
68+
{
69+
PU_OCB_PIB_OCBCSR0_OR,
70+
PU_OCB_PIB_OCBCSR1_OR,
71+
PU_OCB_PIB_OCBCSR2_OR,
72+
PU_OCB_PIB_OCBCSR3_OR
73+
};
74+
75+
void writeOCCSRAM(
76+
const uint32_t address,
77+
uint64_t * buffer,
78+
size_t data_length);
79+
void readOCCSRAM(
80+
const uint32_t address,
81+
uint64_t * buffer,
82+
size_t data_length);
83+
uint64_t makeStart405Instruction(void);
84+
void clear_occ_special_wakeups(void);
85+
86+
#endif /* CPU_PPC64_OCC_H */

src/soc/ibm/power9/Makefile.inc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ bootblock-y += rom_media.c
77
romstage-y += rom_media.c
88
romstage-y += romstage.c
99
romstage-y += vpd.c
10+
romstage-y += occ.c
1011
romstage-y += istep_13_2.c
1112
romstage-y += istep_13_3.c
1213
romstage-y += istep_13_4.c

src/soc/ibm/power9/occ.c

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
/* SPDX-License-Identifier: GPL-2.0-only */
2+
3+
#include <cpu/power/scom.h>
4+
#include <cpu/power/occ.h>
5+
#include <timer.h>
6+
7+
8+
static void pm_ocb_setup(const uint32_t i_ocb_bar)
9+
{
10+
write_scom(OCBCSRn_OR[0], PPC_BIT(OCB_PIB_OCBCSR0_OCB_STREAM_MODE));
11+
write_scom(OCBCSRn_CLEAR[0], PPC_BIT(OCB_PIB_OCBCSR0_OCB_STREAM_TYPE));
12+
write_scom(OCBARn[0], (uint64_t)i_ocb_bar << 32);
13+
}
14+
15+
static void put_ocb_indirect(
16+
const uint32_t i_ocb_req_length,
17+
const uint32_t i_oci_address,
18+
uint64_t* io_ocb_buffer)
19+
{
20+
write_scom(PU_OCB_PIB_OCBAR0, (uint64_t)i_oci_address << 32);
21+
uint64_t ocb_pib = read_scom(PU_OCB_PIB_OCBCSR0_RO);
22+
if((ocb_pib & OCB_PIB_OCBCSR0_OCB_STREAM_MODE)
23+
&& (ocb_pib & OCB_PIB_OCBCSR0_OCB_STREAM_TYPE))
24+
{
25+
uint64_t stream_push_control = read_scom(PU_OCB_OCI_OCBSHCS0_SCOM);
26+
if (stream_push_control & OCB_OCI_OCBSHCS0_PUSH_ENABLE)
27+
for(uint8_t l_counter = 0; l_counter < 4; l_counter++)
28+
{
29+
if (!(stream_push_control & OCB_OCI_OCBSHCS0_PUSH_FULL))
30+
{
31+
break;
32+
}
33+
// Hostboot has delay of 0 here
34+
wait_us(1, false);
35+
stream_push_control = read_scom(PU_OCB_OCI_OCBSHCS0_SCOM);
36+
}
37+
}
38+
for(uint32_t l_index = 0; l_index < i_ocb_req_length; l_index++)
39+
{
40+
write_scom(PU_OCB_PIB_OCBDR0, io_ocb_buffer[l_index]);
41+
}
42+
}
43+
44+
static void get_ocb_indirect(
45+
const uint32_t i_ocb_req_length,
46+
const uint32_t i_oci_address,
47+
uint64_t* io_ocb_buffer)
48+
{
49+
write_scom(PU_OCB_PIB_OCBAR0, (uint64_t)i_oci_address << 32);
50+
for(uint32_t l_loopCount = 0; l_loopCount < i_ocb_req_length; l_loopCount++)
51+
{
52+
io_ocb_buffer[l_loopCount] = read_scom(PU_OCB_PIB_OCBDR0);
53+
}
54+
}
55+
56+
void writeOCCSRAM(
57+
const uint32_t address,
58+
uint64_t * buffer,
59+
size_t data_length)
60+
{
61+
pm_ocb_setup(address);
62+
put_ocb_indirect(
63+
data_length / 8,
64+
address,
65+
buffer);
66+
}
67+
68+
void readOCCSRAM(
69+
const uint32_t address,
70+
uint64_t * buffer,
71+
size_t data_length)
72+
{
73+
pm_ocb_setup(address);
74+
get_ocb_indirect(
75+
data_length / 8,
76+
address,
77+
buffer);
78+
}
79+
80+
uint64_t makeStart405Instruction(void)
81+
{
82+
uint64_t l_epAddr;
83+
readOCCSRAM(
84+
OCC_405_SRAM_ADDRESS + OCC_OFFSET_MAIN_EP,
85+
&l_epAddr,
86+
8);
87+
88+
// The branch instruction is of the form 0x4BXXXXX200000000, where X
89+
// is the address of the 405 main's entry point (alligned as shown).
90+
// Example: If 405 main's EP is FFF5B570, then the branch instruction
91+
// will be 0x4bf5b57200000000. The last two bits of the first byte of
92+
// the branch instruction must be '2' according to the OCC instruction
93+
// set manual.
94+
return OCC_BRANCH_INSTR | (((uint64_t)(BRANCH_ADDR_MASK & l_epAddr)) << 32);
95+
}
96+
97+
void clear_occ_special_wakeups(void)
98+
{
99+
for(size_t chiplet_index = 0;
100+
chiplet_index < NUMBER_OF_EX_CHIPLETS;
101+
++chiplet_index)
102+
{
103+
write_scom_for_chiplet(
104+
EX_CHIPLETS[chiplet_index],
105+
EX_PPM_SPWKUP_OCC,
106+
read_scom_for_chiplet(EX_CHIPLETS[chiplet_index],
107+
EX_PPM_SPWKUP_OCC) & ~PPC_BIT(0));
108+
}
109+
}

0 commit comments

Comments
 (0)