Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
86 changes: 86 additions & 0 deletions src/include/cpu/power/occ.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
/* SPDX-License-Identifier: GPL-2.0-only */

#ifndef CPU_PPC64_OCC_H
#define CPU_PPC64_OCC_H

#include <cpu/power/scom.h>

#define OCC_405_SRAM_ADDRESS (0xFFF40000)
#define OCC_OFFSET_MAIN_EP (0x6C)
#define OCC_BRANCH_INSTR (0x4B00000200000000)
#define BRANCH_ADDR_MASK (0x00FFFFFC)
Comment on lines +10 to +11

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
#define OCC_BRANCH_INSTR (0x4B00000200000000)
#define BRANCH_ADDR_MASK (0x00FFFFFC)
#define OCC_BRANCH_INSTR (0x4800000200000000)
#define BRANCH_ADDR_MASK (0x03FFFFFC)

https://wiki.raptorcs.com/w/images/9/9b/405_um.pdf page 199


#define OCB_PIB_OCBCSR0_OCB_STREAM_MODE (4)
#define OCB_PIB_OCBCSR0_OCB_STREAM_TYPE (5)

#define OCB_OCI_OCBSHCS0_PUSH_ENABLE (31)
#define OCB_OCI_OCBSHCS0_PUSH_FULL (0)

#define PU_OCB_PIB_OCBCSR0_RO (0x0006D011)
#define PU_OCB_OCI_OCBSHCS0_SCOM (0x0006C204)
#define PU_OCB_PIB_OCBDR0 (0x0006D015)

#define PU_OCB_PIB_OCBCSR0_OR (0x0006D013)
#define PU_OCB_PIB_OCBCSR1_OR (0x0006D033)
#define PU_OCB_PIB_OCBCSR2_OR (0x0006D053)
#define PU_OCB_PIB_OCBCSR3_OR (0x0006D073)

#define PU_OCB_PIB_OCBCSR0_CLEAR (0x0006D012)
#define PU_OCB_PIB_OCBCSR1_CLEAR (0x0006D032)
#define PU_OCB_PIB_OCBCSR2_CLEAR (0x0006D052)
#define PU_OCB_PIB_OCBCSR3_CLEAR (0x0006D072)

#define PU_OCB_PIB_OCBAR0 (0x0006D010)
#define PU_OCB_PIB_OCBAR1 (0x0006D030)
#define PU_OCB_PIB_OCBAR2 (0x0006D050)
#define PU_OCB_PIB_OCBAR3 (0x0006D070)

#define EX_PPM_SPWKUP_OCC (0x200F010C)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here you use TP.TPCHIP.NET.PCBSLECxx.PPMC.PPM_COMMON_REGS.PPM_SPWKUP_OCC (0x20...), but EX_CHIPLETS suggests it should be TP.TPCHIP.NET.PCBSLEPxx.PPMQ.PPM_COMMON_REGS.PPM_SPWKUP_OCC (0x10...). This would be fixed by *_for_chiplet(), but someone may search for wrong register in the documentation and/or SCOM dumps.


#define NUMBER_OF_EX_CHIPLETS (6)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Where does it come from? AFAIK there are 12 EXs, 2 per EQ, even though they are probably waken in pairs.

const chiplet_id_t EX_CHIPLETS[NUMBER_OF_EX_CHIPLETS] =
{
EP00_CHIPLET_ID,
EP01_CHIPLET_ID,
EP02_CHIPLET_ID,
EP03_CHIPLET_ID,
EP04_CHIPLET_ID,
EP05_CHIPLET_ID
};
Comment on lines +42 to +49

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Something wrong with indentation here.


const uint64_t OCBARn[4] =
{
PU_OCB_PIB_OCBAR0,
PU_OCB_PIB_OCBAR1,
PU_OCB_PIB_OCBAR2,
PU_OCB_PIB_OCBAR3
};

const uint64_t OCBCSRn_CLEAR[4] =
{
PU_OCB_PIB_OCBCSR0_CLEAR,
PU_OCB_PIB_OCBCSR1_CLEAR,
PU_OCB_PIB_OCBCSR2_CLEAR,
PU_OCB_PIB_OCBCSR3_CLEAR
};

const uint64_t OCBCSRn_OR[4] =
{
PU_OCB_PIB_OCBCSR0_OR,
PU_OCB_PIB_OCBCSR1_OR,
PU_OCB_PIB_OCBCSR2_OR,
PU_OCB_PIB_OCBCSR3_OR
};

void writeOCCSRAM(
const uint32_t address,
uint64_t * buffer,
size_t data_length);
void readOCCSRAM(
const uint32_t address,
uint64_t * buffer,
size_t data_length);
uint64_t makeStart405Instruction(void);
void clear_occ_special_wakeups(void);

#endif /* CPU_PPC64_OCC_H */
1 change: 1 addition & 0 deletions src/soc/ibm/power9/Makefile.inc
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ bootblock-y += rom_media.c
romstage-y += rom_media.c
romstage-y += romstage.c
romstage-y += vpd.c
romstage-y += occ.c
romstage-y += istep_13_2.c
romstage-y += istep_13_3.c
romstage-y += istep_13_4.c
Expand Down
109 changes: 109 additions & 0 deletions src/soc/ibm/power9/occ.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
/* SPDX-License-Identifier: GPL-2.0-only */

#include <cpu/power/scom.h>
#include <cpu/power/occ.h>
#include <timer.h>


static void pm_ocb_setup(const uint32_t i_ocb_bar)
{
write_scom(OCBCSRn_OR[0], PPC_BIT(OCB_PIB_OCBCSR0_OCB_STREAM_MODE));
write_scom(OCBCSRn_CLEAR[0], PPC_BIT(OCB_PIB_OCBCSR0_OCB_STREAM_TYPE));
write_scom(OCBARn[0], (uint64_t)i_ocb_bar << 32);
}

static void put_ocb_indirect(
const uint32_t i_ocb_req_length,
const uint32_t i_oci_address,
uint64_t* io_ocb_buffer)
{
write_scom(PU_OCB_PIB_OCBAR0, (uint64_t)i_oci_address << 32);
uint64_t ocb_pib = read_scom(PU_OCB_PIB_OCBCSR0_RO);
if((ocb_pib & OCB_PIB_OCBCSR0_OCB_STREAM_MODE)
&& (ocb_pib & OCB_PIB_OCBCSR0_OCB_STREAM_TYPE))
Comment on lines +22 to +23

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure if this is at the same indentation level or GitHub just displays it that way, but the second line should begin under next character after first bracket.

{
uint64_t stream_push_control = read_scom(PU_OCB_OCI_OCBSHCS0_SCOM);
if (stream_push_control & OCB_OCI_OCBSHCS0_PUSH_ENABLE)
for(uint8_t l_counter = 0; l_counter < 4; l_counter++)
Comment on lines +26 to +27

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indentation.
I haven't play with push/pull mode, but shouldn't this write data for every read?

{
if (!(stream_push_control & OCB_OCI_OCBSHCS0_PUSH_FULL))
{
break;
}
// Hostboot has delay of 0 here
wait_us(1, false);
stream_push_control = read_scom(PU_OCB_OCI_OCBSHCS0_SCOM);
}
}
for(uint32_t l_index = 0; l_index < i_ocb_req_length; l_index++)
{
write_scom(PU_OCB_PIB_OCBDR0, io_ocb_buffer[l_index]);
}
}

static void get_ocb_indirect(
const uint32_t i_ocb_req_length,
const uint32_t i_oci_address,
uint64_t* io_ocb_buffer)
{
write_scom(PU_OCB_PIB_OCBAR0, (uint64_t)i_oci_address << 32);
for(uint32_t l_loopCount = 0; l_loopCount < i_ocb_req_length; l_loopCount++)
{
io_ocb_buffer[l_loopCount] = read_scom(PU_OCB_PIB_OCBDR0);
}
}

void writeOCCSRAM(
const uint32_t address,
uint64_t * buffer,
size_t data_length)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe add a low verbosity print if this isn't a multiply of 8, here and for read.

{
pm_ocb_setup(address);
put_ocb_indirect(
data_length / 8,
address,
buffer);
}

void readOCCSRAM(
const uint32_t address,
uint64_t * buffer,
size_t data_length)
{
pm_ocb_setup(address);
get_ocb_indirect(
data_length / 8,
address,
buffer);
}

uint64_t makeStart405Instruction(void)
{
uint64_t l_epAddr;
readOCCSRAM(
OCC_405_SRAM_ADDRESS + OCC_OFFSET_MAIN_EP,
&l_epAddr,
8);

// The branch instruction is of the form 0x4BXXXXX200000000, where X
// is the address of the 405 main's entry point (alligned as shown).
// Example: If 405 main's EP is FFF5B570, then the branch instruction
// will be 0x4bf5b57200000000. The last two bits of the first byte of
// the branch instruction must be '2' according to the OCC instruction
// set manual.
Comment on lines +91 to +93

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this comment copied from Hostboot? That 2 at the end indicates that this is absolute branch instruction, instead of relative, it may be worth mentioning here.

return OCC_BRANCH_INSTR | (((uint64_t)(BRANCH_ADDR_MASK & l_epAddr)) << 32);
}

void clear_occ_special_wakeups(void)
{
for(size_t chiplet_index = 0;
chiplet_index < NUMBER_OF_EX_CHIPLETS;
++chiplet_index)
{
write_scom_for_chiplet(

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

scom_and_for_chiplet(EX_CHIPLETS[chiplet_index], EX_PPM_SPWKUP_OCC, ~PPC_BIT(0));

EX_CHIPLETS[chiplet_index],
EX_PPM_SPWKUP_OCC,
read_scom_for_chiplet(EX_CHIPLETS[chiplet_index],
EX_PPM_SPWKUP_OCC) & ~PPC_BIT(0));
}
}