Skip to content

Commit

Permalink
hw/xscom: Add scom infrastructure
Browse files Browse the repository at this point in the history
Currently the top nibble of the "part ID" is used to determine the type
of a xscom_read() / xscom_write() call. This was mainly done for the
benefit of PRD on P8 which would do "targeted" SCOMs to EX (core)
chiplets and rely on skiboot to do find the actual scom address.
Similarly, PRD also relied on this to access the SCOMs of centaur
chips which are accessed via FSI on P8.

On P9 PRD moved to only doing non-targeted scoms where it would
only ever supply a "part ID" which was the fabric ID of the chip
to be SCOMed. The centaur support was also unnecessary since OPAL
didn't support any P9 systems with Centaurs. However, on future
systems we will have to support memory buffer chips again so we need
to expand the SCOM support to accomodate them.

To do this, allow skiboot components to register a SCOM read and write()
function for chip ID. This will allow us to ensure the P8 EX chiplet and
Centaur SCOM code is only ever used on P8, freeing up the Part ID
address space for other uses.

Signed-off-by: Oliver O'Halloran <oohall@gmail.com>
  • Loading branch information
oohal committed Apr 8, 2020
1 parent ec7be08 commit 7b57002
Show file tree
Hide file tree
Showing 2 changed files with 87 additions and 0 deletions.
75 changes: 75 additions & 0 deletions hw/xscom.c
Expand Up @@ -580,11 +580,75 @@ void _xscom_unlock(void)
unlock(&xscom_lock);
}

/* sorted by the scom controller's partid */
static LIST_HEAD(scom_list);

int64_t scom_register(struct scom_controller *new)
{
struct scom_controller *cur;

list_for_each(&scom_list, cur, link) {
if (cur->part_id == new->part_id) {
prerror("Attempted to add duplicate scom, partid %x\n",
new->part_id);
return OPAL_BUSY;
}

if (cur->part_id > new->part_id) {
list_add_before(&scom_list, &new->link, &cur->link);
return 0;
}
}

/* if we never find a larger partid then this is the largest */
list_add_tail(&scom_list, &new->link);

return 0;
}

static struct scom_controller *scom_find(uint32_t partid)
{
struct scom_controller *cur;

list_for_each(&scom_list, cur, link)
if (partid == cur->part_id)
return cur;

return NULL;
}

static int64_t scom_read(struct scom_controller *scom, uint32_t partid,
uint64_t pcbaddr, uint64_t *val)
{
int64_t rc = scom->read(scom, partid, pcbaddr, val);

if (rc) {
prerror("%s: to %x off: %llx rc = %lld\n",
__func__, partid, pcbaddr, rc);
}

return rc;
}

static int64_t scom_write(struct scom_controller *scom, uint32_t partid,
uint64_t pcbaddr, uint64_t val)
{
int64_t rc = scom->write(scom, partid, pcbaddr, val);

if (rc) {
prerror("%s: to %x off: %llx rc = %lld\n",
__func__, partid, pcbaddr, rc);
}

return rc;
}

/*
* External API
*/
int _xscom_read(uint32_t partid, uint64_t pcb_addr, uint64_t *val, bool take_lock)
{
struct scom_controller *scom;
uint32_t gcid;
int rc;

Expand All @@ -611,6 +675,11 @@ int _xscom_read(uint32_t partid, uint64_t pcb_addr, uint64_t *val, bool take_loc
return OPAL_UNSUPPORTED;
break;
default:
/* is it one of our hacks? */
scom = scom_find(partid);
if (scom)
return scom_read(scom, partid, pcb_addr, val);

/**
* @fwts-label XSCOMReadInvalidPartID
* @fwts-advice xscom_read was called with an invalid partid.
Expand Down Expand Up @@ -652,6 +721,7 @@ opal_call(OPAL_XSCOM_READ, opal_xscom_read, 3);

int _xscom_write(uint32_t partid, uint64_t pcb_addr, uint64_t val, bool take_lock)
{
struct scom_controller *scom;
uint32_t gcid;
int rc;

Expand All @@ -666,6 +736,11 @@ int _xscom_write(uint32_t partid, uint64_t pcb_addr, uint64_t val, bool take_loc
gcid = xscom_decode_chiplet(partid, &pcb_addr);
break;
default:
/* is it one of our hacks? */
scom = scom_find(partid);
if (scom)
return scom_write(scom, partid, pcb_addr, val);

/**
* @fwts-label XSCOMWriteInvalidPartID
* @fwts-advice xscom_write was called with an invalid partid.
Expand Down
12 changes: 12 additions & 0 deletions include/xscom.h
Expand Up @@ -197,4 +197,16 @@ extern bool xscom_ok(void);
extern int64_t xscom_read_cfam_chipid(uint32_t partid, uint32_t *chip_id);
extern int64_t xscom_trigger_xstop(void);


struct scom_controller {
uint32_t part_id;
void *private;
int64_t (*read)(struct scom_controller *, uint32_t chip, uint64_t reg, uint64_t *val);
int64_t (*write)(struct scom_controller *, uint32_t chip, uint64_t reg, uint64_t val);

struct list_node link;
};

int64_t scom_register(struct scom_controller *new);

#endif /* __XSCOM_H */

0 comments on commit 7b57002

Please sign in to comment.