summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlistair Popple <alistair@popple.id.au>2016-01-13 17:25:07 +1100
committerAlistair Popple <alistair@popple.id.au>2016-01-13 17:46:42 +1100
commit59bb2d1dcabe41e925f5de19b1b5f99e07392938 (patch)
tree9dd3e1cb1845388f95963884266b2670334175fb
parent4c3473a4785336103cc47de95fddbbba12b12e7a (diff)
downloadpdbg-59bb2d1dcabe41e925f5de19b1b5f99e07392938.tar.gz
pdbg-59bb2d1dcabe41e925f5de19b1b5f99e07392938.zip
Add support for secondary processors
Adds the -p option to select secondary processors and the 'probe' command to detect which processors and threads are present. Signed-off-by: Alistair Popple <alistair@popple.id.au>
-rw-r--r--libpdbg/bmcfsi.c70
-rw-r--r--libpdbg/bmcfsi.h2
-rw-r--r--libpdbg/operations.h12
-rw-r--r--libpdbg/scom.c27
-rw-r--r--src/main.c48
5 files changed, 113 insertions, 46 deletions
diff --git a/libpdbg/bmcfsi.c b/libpdbg/bmcfsi.c
index fe8298f..63ca7c9 100644
--- a/libpdbg/bmcfsi.c
+++ b/libpdbg/bmcfsi.c
@@ -213,14 +213,16 @@ static inline void fsi_send_bit(uint64_t bit)
}
/* Format a CFAM address into an FSI slaveId, command and address. */
-static uint64_t fsi_abs_ar(uint8_t chip_id, uint32_t addr, int read)
+static uint64_t fsi_abs_ar(uint8_t slave_id, int processor_id, uint32_t addr, int read)
{
+ addr |= 0x80000 * processor_id;
+
/* Reformat the address. I'm not sure I fully understand this
* yet but we basically shift the bottom byte and add 0b01
* (for the write word?) */
- addr = ((addr & 0xff00) | ((addr & 0xff) << 2)) << 1;
+ addr = ((addr & 0x3fff00) | ((addr & 0xff) << 2)) << 1;
addr |= 0x3;
- addr |= chip_id << 26;
+ addr |= slave_id << 26;
addr |= (0x8ULL | !!(read)) << 22;
return addr;
@@ -298,7 +300,7 @@ static enum fsi_result fsi_read_resp(uint64_t *result, int len)
}
if (i == 512) {
- printf("Timeout waiting for start bit\n");
+ PR_DEBUG("Timeout waiting for start bit\n");
return FSI_MERR_TIMEOUT;
}
@@ -331,10 +333,10 @@ static enum fsi_result fsi_read_resp(uint64_t *result, int len)
/* Strip the CRC off */
*result = resp >> 4;
- return ack;
+ return ack & 0x3;
}
-static enum fsi_result fsi_d_poll_wait(uint8_t chip_id, uint64_t *resp, int len)
+static enum fsi_result fsi_d_poll_wait(uint8_t slave_id, uint64_t *resp, int len)
{
int i;
uint64_t seq;
@@ -342,7 +344,7 @@ static enum fsi_result fsi_d_poll_wait(uint8_t chip_id, uint64_t *resp, int len)
/* Poll for response if busy */
for (i = 0; i < 512; i++) {
- seq = fsi_d_poll(chip_id) << 59;
+ seq = fsi_d_poll(slave_id) << 59;
fsi_send_seq(seq, 5);
if ((rc = fsi_read_resp(resp, len)) != FSI_BUSY)
@@ -352,11 +354,11 @@ static enum fsi_result fsi_d_poll_wait(uint8_t chip_id, uint64_t *resp, int len)
return rc;
}
-static int fsi_getcfam(struct scom_backend *backend, uint32_t *value, uint32_t addr)
+static int fsi_getcfam(struct scom_backend *backend, int processor_id,
+ uint32_t *value, uint32_t addr)
{
uint64_t seq;
uint64_t resp;
- uint8_t chip_id = slave;
enum fsi_result rc;
/* Format of the read sequence is:
@@ -375,11 +377,11 @@ static int fsi_getcfam(struct scom_backend *backend, uint32_t *value, uint32_t a
* When applying the sequence it should be inverted (active
* low)
*/
- seq = fsi_abs_ar(chip_id, addr, 1) << 36;
+ seq = fsi_abs_ar(slave, processor_id, addr, 1) << 36;
fsi_send_seq(seq, 28);
if ((rc = fsi_read_resp(&resp, 36)) == FSI_BUSY)
- rc = fsi_d_poll_wait(chip_id, &resp, 36);
+ rc = fsi_d_poll_wait(slave, &resp, 36);
if (rc != FSI_ACK) {
PR_ERROR("getcfam error. Response: 0x%01x\n", rc);
@@ -390,11 +392,11 @@ static int fsi_getcfam(struct scom_backend *backend, uint32_t *value, uint32_t a
return rc;
}
-static int fsi_putcfam(struct scom_backend *backend, uint32_t data, uint32_t addr)
+static int fsi_putcfam(struct scom_backend *backend, int processor_id,
+ uint32_t data, uint32_t addr)
{
uint64_t seq;
uint64_t resp;
- uint8_t chip_id = slave;
enum fsi_result rc;
/* Format of the sequence is:
@@ -413,22 +415,23 @@ static int fsi_putcfam(struct scom_backend *backend, uint32_t data, uint32_t add
* When applying the sequence it should be inverted (active
* low)
*/
- seq = fsi_abs_ar(chip_id, addr, 0) << 36;
+ seq = fsi_abs_ar(slave, processor_id, addr, 0) << 36;
seq |= ((uint64_t) data & 0xffffffff) << (4);
fsi_send_seq(seq, 60);
- if ((rc =fsi_read_resp(&resp, 4)) == FSI_BUSY)
- rc = fsi_d_poll_wait(chip_id, &resp, 4);
+ if ((rc = fsi_read_resp(&resp, 4)) == FSI_BUSY)
+ rc = fsi_d_poll_wait(slave, &resp, 4);
if (rc != FSI_ACK) {
- PR_ERROR("putcfam error. Response: 0x%01x\n", rc);
+ PR_DEBUG("putcfam error. Response: 0x%01x\n", rc);
} else
rc = 0;
return rc;
}
-static int fsi_getscom(struct scom_backend *backend, uint64_t *value, uint32_t addr)
+static int fsi_getscom(struct scom_backend *backend, int processor_id,
+ uint64_t *value, uint32_t addr)
{
uint32_t result;
@@ -436,28 +439,32 @@ static int fsi_getscom(struct scom_backend *backend, uint64_t *value, uint32_t a
/* Get scom works by putting the address in FSI_CMD_REG and
* reading the result from FST_DATA[01]_REG. */
- CHECK_ERR(fsi_putcfam(backend, addr, FSI_CMD_REG));
- CHECK_ERR(fsi_getcfam(backend, &result, FSI_DATA0_REG));
+ CHECK_ERR(fsi_putcfam(backend, processor_id, addr, FSI_CMD_REG));
+ CHECK_ERR(fsi_getcfam(backend, processor_id, &result, FSI_DATA0_REG));
*value = (uint64_t) result << 32;
- CHECK_ERR(fsi_getcfam(backend, &result, FSI_DATA1_REG));
+ CHECK_ERR(fsi_getcfam(backend, processor_id, &result, FSI_DATA1_REG));
*value |= result;
return 0;
}
-static int fsi_putscom(struct scom_backend *backend, uint64_t value, uint32_t addr)
+static int fsi_putscom(struct scom_backend *backend, int processor_id,
+ uint64_t value, uint32_t addr)
{
usleep(FSI2PIB_RELAX);
- CHECK_ERR(fsi_putcfam(backend, FSI_RESET_CMD, FSI_RESET_REG));
- CHECK_ERR(fsi_putcfam(backend, (value >> 32) & 0xffffffff, FSI_DATA0_REG));
- CHECK_ERR(fsi_putcfam(backend, value & 0xffffffff, FSI_DATA1_REG));
- CHECK_ERR(fsi_putcfam(backend, FSI_CMD_REG_WRITE | addr, FSI_CMD_REG));
+ CHECK_ERR(fsi_putcfam(backend, processor_id, FSI_RESET_CMD, FSI_RESET_REG));
+ CHECK_ERR(fsi_putcfam(backend, processor_id, (value >> 32) & 0xffffffff, FSI_DATA0_REG));
+ CHECK_ERR(fsi_putcfam(backend, processor_id, value & 0xffffffff, FSI_DATA1_REG));
+ CHECK_ERR(fsi_putcfam(backend, processor_id, FSI_CMD_REG_WRITE | addr, FSI_CMD_REG));
return 0;
}
-struct scom_backend *fsi_init(int slave_id)
+struct scom_backend *fsi_init(void)
{
+ int i;
+ uint32_t val;
+ uint64_t val64;
struct scom_backend *backend;
if (gpio_reg) {
@@ -490,7 +497,7 @@ struct scom_backend *fsi_init(int slave_id)
write_gpio(FSI_ENABLE, 1);
write_gpio(CRONUS_SEL, 1); //Set Cronus control to BMC
- slave = slave_id;
+ slave = 0;
backend->getscom = fsi_getscom;
backend->putscom = fsi_putscom;
backend->getcfam = fsi_getcfam;
@@ -500,8 +507,11 @@ struct scom_backend *fsi_init(int slave_id)
fsi_break();
- /* Make sure the FSI2PIB engine is in a good state */
- if (fsi_putcfam(backend, FSI_SET_PIB_RESET, FSI_SET_PIB_RESET_REG))
+ /* Clear own id on the master CFAM to access hMFSI ports */
+ if (fsi_getcfam(backend, 0, &val, 0x800))
+ return NULL;
+ val &= ~(PPC_BIT32(6) | PPC_BIT32(7));
+ if (fsi_putcfam(backend, 0, val, 0x800))
return NULL;
return backend;
diff --git a/libpdbg/bmcfsi.h b/libpdbg/bmcfsi.h
index 8635b07..7112bd9 100644
--- a/libpdbg/bmcfsi.h
+++ b/libpdbg/bmcfsi.h
@@ -20,7 +20,7 @@
#define SLAVE_ID 0x0
/* backend initialisation */
-struct scom_backend *fsi_init(int slave_id);
+struct scom_backend *fsi_init(void);
void fsi_destroy(struct scom_backend *backend);
#endif
diff --git a/libpdbg/operations.h b/libpdbg/operations.h
index 5e4bdda..7c8e1a7 100644
--- a/libpdbg/operations.h
+++ b/libpdbg/operations.h
@@ -38,10 +38,11 @@
/* Structure to allow alternative backend implentations */
struct scom_backend {
void (*destroy)(struct scom_backend *backend);
- int (*getscom)(struct scom_backend *backend, uint64_t *value, uint32_t addr);
- int (*putscom)(struct scom_backend *backend, uint64_t value, uint32_t addr);
- int (*getcfam)(struct scom_backend *backend, uint32_t *value, uint32_t addr);
- int (*putcfam)(struct scom_backend *backend, uint32_t value, uint32_t addr);
+ int (*getscom)(struct scom_backend *backend, int processor_id, uint64_t *value, uint32_t addr);
+ int (*putscom)(struct scom_backend *backend, int processor_id, uint64_t value, uint32_t addr);
+ int (*getcfam)(struct scom_backend *backend, int processor_id, uint32_t *value, uint32_t addr);
+ int (*putcfam)(struct scom_backend *backend, int processor_id, uint32_t value, uint32_t addr);
+ int processor_id;
void *priv;
};
@@ -60,8 +61,9 @@ int ram_start_chip(uint64_t chip, uint64_t thread_active);
int gdbserver_start(uint16_t port);
/* scom backend functions. Most other operations use these. */
-int backend_init(int slave_id);
+int backend_init(int processor_id);
void backend_destroy(void);
+void backend_set_processor(int processor_id);
int getscom(uint64_t *value, uint32_t addr);
int putscom(uint64_t value, uint32_t addr);
int getcfam(uint32_t *value, uint32_t addr);
diff --git a/libpdbg/scom.c b/libpdbg/scom.c
index 2e4d93b..9a31c04 100644
--- a/libpdbg/scom.c
+++ b/libpdbg/scom.c
@@ -16,20 +16,35 @@
#include <stdint.h>
#include <stdio.h>
+#include "bitutils.h"
#include "bmcfsi.h"
#include "operations.h"
struct scom_backend *backend = NULL;
-int backend_init(int slave_id)
+#define FSI_SET_PIB_RESET_REG 0x1007
+#define FSI_SET_PIB_RESET PPC_BIT32(0)
+
+int backend_init(int processor_id)
{
- backend = fsi_init(slave_id);
+ backend = fsi_init();
if (!backend)
return -1;
+ backend->processor_id = processor_id;
+
+ /* Make sure the FSI2PIB engine is in a good state */
+ if (putcfam(FSI_SET_PIB_RESET, FSI_SET_PIB_RESET_REG))
+ return -1;
+
return 0;
}
+void backend_set_processor(int processor_id)
+{
+ backend->processor_id = processor_id;
+}
+
void backend_destroy(void)
{
if (!backend || backend->destroy)
@@ -43,7 +58,7 @@ int getscom(uint64_t *value, uint32_t addr)
return -1;
}
- return backend->getscom(backend, value, addr);
+ return backend->getscom(backend, backend->processor_id, value, addr);
}
int putscom(uint64_t value, uint32_t addr)
@@ -53,7 +68,7 @@ int putscom(uint64_t value, uint32_t addr)
return -1;
}
- return backend->putscom(backend, value, addr);
+ return backend->putscom(backend, backend->processor_id, value, addr);
}
int getcfam(uint32_t *value, uint32_t addr)
@@ -63,7 +78,7 @@ int getcfam(uint32_t *value, uint32_t addr)
return -1;
}
- return backend->getcfam(backend, value, addr);
+ return backend->getcfam(backend, backend->processor_id, value, addr);
}
int putcfam(uint32_t value, uint32_t addr)
@@ -73,5 +88,5 @@ int putcfam(uint32_t value, uint32_t addr)
return -1;
}
- return backend->putcfam(backend, value, addr);
+ return backend->putcfam(backend, backend->processor_id, value, addr);
}
diff --git a/src/main.c b/src/main.c
index 6c39a9e..2d13256 100644
--- a/src/main.c
+++ b/src/main.c
@@ -25,9 +25,13 @@
#include <bmcfsi.h>
#include <operations.h>
+/* EX/Chiplet GP0 SCOM address */
+#define SCOM_EX_GP0 0x10000000
+
enum command { GETCFAM = 1, PUTCFAM, GETSCOM, PUTSCOM, \
GETMEM, PUTMEM, GETGPR, GETNIA, GETSPR, \
- STOPCHIP, STARTCHIP, THREADSTATUS };
+ STOPCHIP, STARTCHIP, THREADSTATUS, \
+ PROBE };
#define MAX_CMD_ARGS 2
enum command cmd = 0;
@@ -36,6 +40,7 @@ static int cmd_arg_count = 0;
/* At the moment all commands only take some kind of number */
static uint64_t cmd_args[MAX_CMD_ARGS];
+static int processor = 0;
static int chip = 0;
static int thread = 0;
@@ -43,7 +48,8 @@ static void print_usage(char *pname)
{
printf("Usage: %s [options] command ...\n\n", pname);
printf(" Options:\n");
- printf("\t-c, --chip=chip\n");
+ printf("\t-p, --processor=processor-id\n");
+ printf("\t-c, --chip=chiplet-id\n");
printf("\t-t, --thread=thread\n");
printf("\t-h, --help\n");
printf("\n");
@@ -59,6 +65,7 @@ static void print_usage(char *pname)
printf("\tstopchip\n");
printf("\tstartchip <threads>\n");
printf("\tthreadstatus\n");
+ printf("\tprobe\n");
}
enum command parse_cmd(char *optarg)
@@ -96,6 +103,9 @@ enum command parse_cmd(char *optarg)
} else if (strcmp(optarg, "threadstatus") == 0) {
cmd = THREADSTATUS;
cmd_arg_count = 0;
+ } else if (strcmp(optarg, "probe") == 0) {
+ cmd = PROBE;
+ cmd_arg_count = 0;
}
return cmd;
@@ -106,13 +116,14 @@ static bool parse_options(int argc, char *argv[])
int c, oidx = 0, cmd_arg_idx = 0;
bool opt_error = true;
struct option long_opts[] = {
+ {"processor", required_argument, NULL, 'p'},
{"chip", required_argument, NULL, 'c'},
{"thread", required_argument, NULL, 't'},
{"help", no_argument, NULL, 'h'},
};
do {
- c = getopt_long(argc, argv, "-c:t:h", long_opts, &oidx);
+ c = getopt_long(argc, argv, "-p:c:t:h", long_opts, &oidx);
switch(c) {
case 1:
/* Positional argument */
@@ -128,6 +139,11 @@ static bool parse_options(int argc, char *argv[])
}
break;
+ case 'p':
+ errno = 0;
+ processor = strtoull(optarg, NULL, 0);
+ opt_error = errno;
+ break;
case 't':
errno = 0;
thread = strtoull(optarg, NULL, 0);
@@ -153,6 +169,27 @@ static bool parse_options(int argc, char *argv[])
return opt_error;
}
+static uint64_t probe(void)
+{
+ int i, j;
+ uint64_t addr, value;
+
+ /* Probe for processors by trying to read all possible
+ * 0xf000f device-id registers. */
+ printf("Probing for valid processors...\n");
+ for (i = 0; i < 8; i++) {
+ backend_set_processor(i);
+ if (!getscom(&value, 0xf000f) && value) {
+ printf("\tProcessor-ID %d: 0x%llx\n", i, value);
+ for (j = 0; j < 0xf; j++) {
+ addr = SCOM_EX_GP0 | (j << 24);
+ if (!getscom(&value, addr) && value)
+ printf("\t\tChiplet-ID %d present\n", j);
+ }
+ }
+ }
+}
+
static uint64_t active_threads;
/*
@@ -208,7 +245,7 @@ int main(int argc, char *argv[])
if (parse_options(argc, argv))
return 1;
- if (backend_init(SLAVE_ID)) {
+ if (backend_init(processor)) {
PR_ERROR("Unable to initialise backend\n");
return 1;
}
@@ -293,6 +330,9 @@ int main(int argc, char *argv[])
case THREADSTATUS:
print_thread_status();
break;
+ case PROBE:
+ probe();
+ break;
}
backend_destroy();
OpenPOWER on IntegriCloud