diff options
author | Alistair Popple <alistair@popple.id.au> | 2016-01-13 17:25:07 +1100 |
---|---|---|
committer | Alistair Popple <alistair@popple.id.au> | 2016-01-13 17:46:42 +1100 |
commit | 59bb2d1dcabe41e925f5de19b1b5f99e07392938 (patch) | |
tree | 9dd3e1cb1845388f95963884266b2670334175fb | |
parent | 4c3473a4785336103cc47de95fddbbba12b12e7a (diff) | |
download | pdbg-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.c | 70 | ||||
-rw-r--r-- | libpdbg/bmcfsi.h | 2 | ||||
-rw-r--r-- | libpdbg/operations.h | 12 | ||||
-rw-r--r-- | libpdbg/scom.c | 27 | ||||
-rw-r--r-- | src/main.c | 48 |
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); } @@ -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(); |