aboutsummaryrefslogtreecommitdiffstats
path: root/roms/skiboot/external/xscom-utils
diff options
context:
space:
mode:
Diffstat (limited to 'roms/skiboot/external/xscom-utils')
-rw-r--r--roms/skiboot/external/xscom-utils/.gitignore3
-rw-r--r--roms/skiboot/external/xscom-utils/Makefile61
-rwxr-xr-xroms/skiboot/external/xscom-utils/adu_scoms.py300
-rw-r--r--roms/skiboot/external/xscom-utils/getscom.123
-rw-r--r--roms/skiboot/external/xscom-utils/getscom.c167
-rw-r--r--roms/skiboot/external/xscom-utils/getsram.123
-rw-r--r--roms/skiboot/external/xscom-utils/getsram.c132
-rw-r--r--roms/skiboot/external/xscom-utils/putscom.118
-rw-r--r--roms/skiboot/external/xscom-utils/putscom.c115
-rw-r--r--roms/skiboot/external/xscom-utils/sram.c139
-rw-r--r--roms/skiboot/external/xscom-utils/sram.h14
-rw-r--r--roms/skiboot/external/xscom-utils/xscom.c206
-rw-r--r--roms/skiboot/external/xscom-utils/xscom.h26
13 files changed, 1227 insertions, 0 deletions
diff --git a/roms/skiboot/external/xscom-utils/.gitignore b/roms/skiboot/external/xscom-utils/.gitignore
new file mode 100644
index 000000000..43e219f9c
--- /dev/null
+++ b/roms/skiboot/external/xscom-utils/.gitignore
@@ -0,0 +1,3 @@
+getscom
+getsram
+putscom
diff --git a/roms/skiboot/external/xscom-utils/Makefile b/roms/skiboot/external/xscom-utils/Makefile
new file mode 100644
index 000000000..69ce87a72
--- /dev/null
+++ b/roms/skiboot/external/xscom-utils/Makefile
@@ -0,0 +1,61 @@
+# SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
+CC = $(CROSS_COMPILE)gcc
+
+XSCOM_VERSION ?= $(shell ../../make_version.sh xscom-utils)
+CFLAGS += -O2 -g -Wall -m64
+
+prefix = /usr/local/
+sbindir = $(prefix)/sbin
+datadir = $(prefix)/share
+mandir = $(datadir)/man
+
+%.o: %.c
+ $(Q_CC)$(COMPILE.c) $< -o $@
+
+# Use make V=1 for a verbose build.
+ifndef V
+ Q_CC= @echo ' CC ' $@;
+ Q_LINK= @echo ' LINK ' $@;
+ Q_LN= @echo ' LN ' $@;
+ Q_MKDIR=@echo ' MKDIR ' $@;
+endif
+
+all: getscom putscom getsram
+
+getscom: getscom.o xscom.o version.o
+ $(Q_LINK)$(LINK.o) -o $@ $^
+
+getsram: getsram.o xscom.o sram.o version.o
+ $(Q_LINK)$(LINK.o) -o $@ $^
+
+putscom: putscom.o xscom.o version.o
+ $(Q_LINK)$(LINK.o) -o $@ $^
+
+install: all
+ install -D getscom $(DESTDIR)$(sbindir)/getscom
+ install -D putscom $(DESTDIR)$(sbindir)/putscom
+ install -D getsram $(DESTDIR)$(sbindir)/getsram
+ install -D -m 0644 getscom.1 $(DESTDIR)$(mandir)/man1/getscom.1
+ install -D -m 0644 putscom.1 $(DESTDIR)$(mandir)/man1/putscom.1
+ install -D -m 0644 getsram.1 $(DESTDIR)$(mandir)/man1/getsram.1
+
+.PHONY: clean
+clean:
+ rm -rf *.[od] getscom putscom getsram
+
+.PHONY: distclean
+distclean: clean
+ rm -rf *.c~ *.h~ *.i *.s Makefile~ .version version.c
+
+version.c: ../../make_version.sh .version
+ @(if [ "a$(XSCOM_VERSION)" = "a" ]; then \
+ echo "#error You need to set XSCOM_VERSION environment variable" > $@ ;\
+ else \
+ echo "const char version[] = \"$(XSCOM_VERSION)\";" ;\
+ fi) > $@
+
+.PHONY: VERSION-always
+.version: VERSION-always
+ @echo $(XSCOM_VERSION) > $@.tmp
+ @cmp -s $@ $@.tmp || cp $@.tmp $@
+ @rm -f $@.tmp
diff --git a/roms/skiboot/external/xscom-utils/adu_scoms.py b/roms/skiboot/external/xscom-utils/adu_scoms.py
new file mode 100755
index 000000000..e90634190
--- /dev/null
+++ b/roms/skiboot/external/xscom-utils/adu_scoms.py
@@ -0,0 +1,300 @@
+#!/usr/bin/python
+# SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
+#
+# Python library for in-band SCom access
+# (based on xscom-utils from OPAL firmware)
+#
+# Copyright 2018 IBM Corp.
+
+import os, sys, struct, getopt
+
+class XSCom(object):
+ def __init__(self):
+ self.name = "xscom"
+ self.base = "/sys/kernel/debug/powerpc/scom/"
+ self.enabled = False
+ self.setup = False
+ self.chips = []
+ self.dirs = []
+ self.key_val_bin = {}
+ self.file = "/access"
+
+ if os.path.exists(self.base):
+ self.enabled = True
+
+ if not self.scan_chips():
+ raise ValueError
+
+ def scan_chips(self):
+ if not self.enabled:
+ print("Not supported")
+ return False
+
+ for i in os.listdir(self.base):
+ if os.path.isdir(self.base+i):
+ self.dirs.append(i)
+ self.chips.append(int(i,16))
+
+ for i in self.dirs:
+ try:
+ b = open(self.base+i+self.file, "rb+")
+ self.key_val_bin[int(i,16)] = b
+ except:
+ print("Count not open"+self.base+i+self.file)
+ return False
+
+ self.setup = True
+ return True
+
+ def is_supported(self):
+ return self.enabled
+
+ def get_chip_ids(self):
+ return list(self.key_val_bin.keys())
+
+ def mangle_addr(self, addr):
+ tmp = (addr & 0xf000000000000000) >> 4
+ addr = (addr & 0x00ffffffffffffff)
+ addr = addr | tmp
+ return (addr << 3)
+
+ def xscom_read(self, chip_id, addr):
+ if not isinstance(chip_id, int) or not isinstance(addr, int):
+ print("xscom_read: Input paramater type mismatch")
+ return -1
+
+ if chip_id not in self.key_val_bin:
+ print("Invalid Chip id")
+ return -1
+
+ saddr = self.mangle_addr(addr)
+ fd = self.key_val_bin.get(chip_id)
+ fd.seek(saddr, 0)
+ return struct.unpack('Q',fd.read(8))[0]
+
+ def xscom_read_spl(self, chip_id, addr):
+ if not isinstance(chip_id, int) or not isinstance(addr, int):
+ print("xscom_read: Input paramater type mismatch")
+ return -1
+
+ if chip_id not in self.key_val_bin:
+ print("Invalid Chip id")
+ return -1
+
+ saddr = self.mangle_addr(addr)
+ fd = self.key_val_bin.get(chip_id)
+ fd.seek(saddr, 0)
+ val = struct.unpack('Q',fd.read(8))[0]
+ fd.close()
+ try:
+ b = open(self.key_val_path.get(chip_id), "rb+")
+ except:
+ print("Reopen failed")
+ return val
+ self.key_val_bin[chip_id] = b
+ return val
+
+ def xscom_write(self, chip_id, addr, val):
+ if chip_id not in self.key_val_bin:
+ print("Invalid Chip id")
+ return -1
+
+ c = struct.pack('Q',val)
+ saddr = self.mangle_addr(addr)
+ fd = self.key_val_bin.get(chip_id)
+
+ try:
+ fd.seek(saddr, 0)
+ fd.write(c)
+ # write again just to be sure
+ fd.seek(saddr, 0)
+ fd.write(c)
+ except:
+ print("Write() error")
+ return -1
+
+ def xscom_read_ex(self, ex_target_id, addr):
+ if not isinstance(ex_target_id, int) or not isinstance(addr, int):
+ print("xscom_read_ex: Input paramater type mismatch")
+ return -1
+
+ chip_id = ex_target_id >> 4
+ addr |= (ex_target_id & 0xf) << 24;
+ return self.xscom_read(chip_id, addr, val);
+
+ def xscom_write_ex(self, ex_target_id, addr, val):
+ chip_id = ex_target_id >> 4
+ addr |= (ex_target_id & 0xf) << 24;
+ return self.xscom_write(chip_id, addr, val)
+
+class GetSCom(object):
+ def __init__(self):
+ self.name = "getscom"
+ self.backend = XSCom()
+ self.listchip = False
+ self.chip_id = 0
+ self.chips = False
+ self.addr = 0
+ self.flg_addr = False
+
+ if not self.backend.is_supported():
+ print("In-Band SCom not supported Exiting....")
+ raise ValueError
+
+ def set_chip(self, chip_id):
+ self.chip_id = chip_id
+ self.chips = True
+
+ def set_addr(self, scom_addr):
+ self.addr = scom_addr
+ self.flg_addr = True
+
+ def print_usage(self):
+ print("usage: getscom [-c|--chip chip-id] addr")
+ print(" getscom -l|--list-chips")
+ print(" getscom -h|--help")
+ sys.exit(0)
+
+
+ def chip_info(self, chip_id):
+ val = self.backend.xscom_read(chip_id, 0xf000f)
+ if val < 0:
+ print("Error in scom read")
+ raise ValueError
+
+ c_id = val >> 44
+ id = c_id & 0xff
+ if id == 0xef:
+ name = "P8E (Murano) processor"
+ elif id == 0xea:
+ name = "P8 (Venice) processor"
+ elif id == 0xd3:
+ name = "P8NVL (Naples) processor"
+ elif id == 0xd1:
+ name = "P9 (Nimbus) processor"
+ elif id == 0xd4:
+ name = "P9 (Cumulus) processor"
+ elif id == 0xd9:
+ name = "P9P (Axone) processor"
+ elif id == 0xda:
+ name = "P10 processor"
+ elif id == 0xe9:
+ name = "Centaur memory buffer"
+ else:
+ name = "Unknown ID 0x%x"%id
+
+ print(("%08x | DD%s.%s | %s"%(chip_id, ((c_id >> 16) & 0xf), ((c_id >> 8) & 0xf), name)))
+
+ def parse_args(self):
+ try:
+ optlist, sys.argv = getopt.getopt(sys.argv[1:], "lhc:", ["chip", "list-chips", "help"])
+ except getopt.GetoptError as err:
+ print(str(err))
+ self.print_usage()
+ sys.exit(0)
+
+ if len(optlist) == 0:
+ self.print_usage()
+ sys.exit(0)
+
+ for opt, arg in optlist:
+ if opt in [ "-h", "--help"]:
+ self.print_usage()
+ sys.exit(0)
+
+ elif opt in [ "-l", "--list-chips"]:
+ self.listchip = True
+
+ elif opt in ["-c", "--chip"]:
+ self.chip_id = int(arg, 16)
+ self.chips = True
+
+ if sys.argv:
+ self.addr = int(sys.argv.pop(), 16)
+ self.flg_addr = True
+
+ if self.listchip:
+ print("Chip ID | Rev | Chip type")
+ print("---------|-------|-----------")
+ for i in self.backend.get_chip_ids():
+ self.chip_info(i)
+
+ sys.exit(0)
+
+ def run_command(self):
+ if self.chips and self.flg_addr:
+ print(hex(self.backend.xscom_read(self.chip_id, self.addr)))
+
+ def list_chips(self):
+ print("Chip ID | Rev | Chip type")
+ print("---------|-------|-----------")
+ for i in self.backend.get_chip_ids():
+ self.chip_info(i)
+
+ raise ValueError
+
+ def execute(self, chip_id, addr):
+ return self.backend.xscom_read(chip_id, addr)
+
+ def execute_spl(self, chip_id, addr):
+ return self.backend.xscom_read_spl(chip_id, addr)
+
+class PutSCom(object):
+ def __init__(self):
+ self.name = "putscom"
+ self.backend = XSCom()
+ self.chip_id = 0
+ self.chips = False
+ self.addr = 0
+ self.value = 0
+
+ if not self.backend.is_supported():
+ print("In-Band SCom not supported Exiting....")
+ raise ValueError
+
+ def set_addr(self, addr):
+ self.addr = addr
+
+ def set_value(self, value):
+ self.value = value
+
+ def print_usage(self):
+ print("usage: putscom [-c|--chip chip-id] addr value")
+ print(" putscom -h|--help")
+ sys.exit(0)
+
+ def parse_args(self):
+ try:
+ optlist, sys.argv = getopt.getopt(sys.argv[1:], "hc:", ["chip", "help"])
+ except getopt.GetoptError as err:
+ print(str(err))
+ self.print_usage()
+ sys.exit(0)
+
+ if len(optlist) == 0:
+ self.print_usage()
+ sys.exit(0)
+
+ for opt, arg in optlist:
+ if opt in [ "-h", "--help"]:
+ self.print_usage()
+ sys.exit(0)
+
+ elif opt in ["-c", "--chip"]:
+ self.chip_id = int(arg, 16)
+ self.chips = True
+
+ if sys.argv:
+ self.value = int(sys.argv.pop(), 16)
+ self.addr = int(sys.argv.pop(), 16)
+
+ if self.chips:
+ self.backend.xscom_write(self.chip_id, self.addr, self.value)
+
+ def run_command(self):
+ if self.chips:
+ self.backend.xscom_write(self.chip_id, self.addr, self.value)
+
+ def execute(self, chip_id, addr, value):
+ self.backend.xscom_write(chip_id, addr, value)
+
diff --git a/roms/skiboot/external/xscom-utils/getscom.1 b/roms/skiboot/external/xscom-utils/getscom.1
new file mode 100644
index 000000000..295b99d56
--- /dev/null
+++ b/roms/skiboot/external/xscom-utils/getscom.1
@@ -0,0 +1,23 @@
+.TH XSCOM "1" "September 2016"
+.SH NAME
+getscom \- part of xscom utils
+.SH SYNOPIS
+.TP
+\fBgetscom\fP [\-c | \-\-chip \fIchip\-id\fP] \fIaddr\fP
+.TP
+\fBgetscom\fP [\-l | \-\-list\-chips]
+.TP
+\fBgetscom\fP [\-v | \-\-version]
+.SH DESCRIPTION
+\fBgetscom\fP utility provides an interface to query the
+registers of the different chipsets of an OpenPower system.
+.SS Options
+.TP
+\fB\-c|\-\-chip-id\fP \fIchip-id\fP
+Specify chipset where to read register at \fIaddr\fP
+.TP
+\fB\-l|\-\-list\-chips\fP
+List the chipsets found on the system
+.TP
+\fB\-v|\-\-version\fP
+Display version of the tool
diff --git a/roms/skiboot/external/xscom-utils/getscom.c b/roms/skiboot/external/xscom-utils/getscom.c
new file mode 100644
index 000000000..67596e618
--- /dev/null
+++ b/roms/skiboot/external/xscom-utils/getscom.c
@@ -0,0 +1,167 @@
+// SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
+/*
+ * getscom
+ *
+ * Copyright 2014-2017 IBM Corp.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <getopt.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include <inttypes.h>
+
+#include "xscom.h"
+
+static void print_usage(int code)
+{
+ printf("usage: getscom [-c|--chip chip-id] [-b|--list-bits] addr\n");
+ printf(" getscom -l|--list-chips\n");
+ printf(" getscom -v|--version\n");
+ printf("\n");
+ printf(" NB: --list-bits shows which PPC bits are set\n");
+ exit(code);
+}
+
+static void print_chip_info(uint32_t chip_id)
+{
+ uint64_t f000f, cfam_id;
+ const char *name;
+ char uname_buf[64];
+ int rc;
+
+ rc = xscom_read(chip_id, 0xf000f, &f000f);
+ if (rc)
+ return;
+
+ cfam_id = f000f >> 44;
+
+ switch(cfam_id & 0xff) {
+ case 0xef:
+ name = "P8E (Murano) processor";
+ break;
+ case 0xea:
+ name = "P8 (Venice) processor";
+ break;
+ case 0xd3:
+ name = "P8NVL (Naples) processor";
+ break;
+ case 0xd1:
+ name = "P9 (Nimbus) processor";
+ break;
+ case 0xd4:
+ name = "P9 (Cumulus) processor";
+ break;
+ case 0xd9:
+ name = "P9P (Axone) processor";
+ break;
+ case 0xda:
+ name = "P10 processor";
+ break;
+ case 0xe9:
+ name = "Centaur memory buffer";
+ break;
+ default:
+ snprintf(uname_buf, sizeof(uname_buf), "Unknown ID 0x%02lx",
+ cfam_id & 0xff);
+ name = uname_buf;
+ }
+
+ printf("%08x | DD%lx.%lx | %s\n",
+ chip_id, (cfam_id >> 16) & 0xf, (cfam_id >> 8) & 0xf, name);
+}
+
+extern const char version[];
+
+int main(int argc, char *argv[])
+{
+ uint64_t val, addr = -1ull;
+ uint32_t def_chip, chip_id = 0xffffffff;
+ bool list_chips = false;
+ bool no_work = false;
+ bool list_bits = false;
+ int rc;
+
+ while(1) {
+ static struct option long_opts[] = {
+ {"chip", required_argument, NULL, 'c'},
+ {"list-chips", no_argument, NULL, 'l'},
+ {"help", no_argument, NULL, 'h'},
+ {"version", no_argument, NULL, 'v'},
+ {"list-bits", no_argument, NULL, 'b'},
+ };
+ int c, oidx = 0;
+
+ c = getopt_long(argc, argv, "-c:bhlv", long_opts, &oidx);
+ if (c == EOF)
+ break;
+ switch(c) {
+ case 1:
+ addr = strtoull(optarg, NULL, 16);
+ break;
+ case 'c':
+ chip_id = strtoul(optarg, NULL, 16);
+ break;
+ case 'h':
+ print_usage(0);
+ break;
+ case 'l':
+ list_chips = true;
+ break;
+ case 'b':
+ list_bits = true;
+ break;
+ case 'v':
+ printf("xscom utils version %s\n", version);
+ exit(0);
+ default:
+ exit(1);
+ }
+ }
+
+ if (addr == -1ull)
+ no_work = true;
+ if (no_work && !list_chips) {
+ fprintf(stderr, "Invalid or missing address\n");
+ print_usage(1);
+ }
+
+ def_chip = xscom_init();
+ if (def_chip == 0xffffffff) {
+ fprintf(stderr, "No valid XSCOM chip found\n");
+ exit(1);
+ }
+ if (list_chips) {
+ printf("Chip ID | Rev | Chip type\n");
+ printf("---------|-------|--------\n");
+ xscom_for_each_chip(print_chip_info);
+ }
+ if (no_work)
+ return 0;
+ if (chip_id == 0xffffffff)
+ chip_id = def_chip;
+
+ rc = xscom_read(chip_id, addr, &val);
+ if (rc) {
+ fprintf(stderr,"Error %d reading XSCOM\n", rc);
+ exit(1);
+ }
+
+ printf("%016" PRIx64, val);
+
+ if (list_bits) {
+ int i;
+
+ printf(" - set: ");
+
+ for (i = 0; i < 64; i++)
+ if (val & PPC_BIT(i))
+ printf("%d ", i);
+ }
+
+ putchar('\n');
+
+ return 0;
+}
+
diff --git a/roms/skiboot/external/xscom-utils/getsram.1 b/roms/skiboot/external/xscom-utils/getsram.1
new file mode 100644
index 000000000..19b297414
--- /dev/null
+++ b/roms/skiboot/external/xscom-utils/getsram.1
@@ -0,0 +1,23 @@
+.TH XSCOM "1" "January 2018"
+.SH NAME
+getsram \- part of xscom utils
+.SH SYNOPIS
+.TP
+\fBgetsram\fP [\-c | \-\-chip \fIchip\-id\fP] \fIaddr\fP
+.TP
+\fBgetsram\fP [\-n | \-\-occ\-channel \fIchan\fP]
+.TP
+\fBgetsram\fP [\-v | \-\-version]
+.SH DESCRIPTION
+\fBgetsram\fP utility provides an interface to query the
+OCC RAM of an OpenPower system.
+.SS Options
+.TP
+\fB\-c|\-\-chip-id\fP \fIchip-id\fP
+Specify chipset where to read register at \fIaddr\fP
+.TP
+\fB\-n|\-\-occ\-channel\fP
+Specify the channel : 0, 1, 2 or 3
+.TP
+\fB\-v|\-\-version\fP
+Display version of the tool
diff --git a/roms/skiboot/external/xscom-utils/getsram.c b/roms/skiboot/external/xscom-utils/getsram.c
new file mode 100644
index 000000000..7d9c4bfac
--- /dev/null
+++ b/roms/skiboot/external/xscom-utils/getsram.c
@@ -0,0 +1,132 @@
+// SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
+/*
+ * Read SRAM
+ *
+ * Copyright 2014-2018 IBM Corp.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <getopt.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include <inttypes.h>
+
+#include "xscom.h"
+#include "sram.h"
+
+static void print_usage(int code)
+{
+ printf("usage: getsram [opts] addr\n");
+ printf(" -c|--chip <chip-id>\n");
+ printf(" -l|--length <size to read>\n");
+ printf(" -n|--occ-channel <chan>\n");
+ printf(" -f|--file <filename>\n");
+ printf(" -v|--version\n");
+ exit(code);
+}
+
+extern const char version[];
+
+int main(int argc, char *argv[])
+{
+ uint64_t val, addr = -1ull, length = 8;
+ uint32_t def_chip, chip_id = 0xffffffff;
+ int rc;
+ int occ_channel = 0;
+ char *filename = NULL;
+ FILE *f = stdout;
+
+ while(1) {
+ static struct option long_opts[] = {
+ {"chip", required_argument, NULL, 'c'},
+ {"occ-channel", required_argument, NULL, 'n'},
+ {"help", no_argument, NULL, 'h'},
+ {"version", no_argument, NULL, 'v'},
+ {"length", required_argument, NULL, 'l'},
+ {"file", required_argument, NULL, 'f'},
+ };
+ int c, oidx = 0;
+
+ c = getopt_long(argc, argv, "-c:n:hl:vf:", long_opts, &oidx);
+ if (c == EOF)
+ break;
+ switch(c) {
+ case 1:
+ addr = strtoull(optarg, NULL, 16);
+ break;
+ case 'c':
+ chip_id = strtoul(optarg, NULL, 16);
+ break;
+ case 'n':
+ occ_channel = strtoul(optarg, NULL, 0);
+ if (occ_channel < 0 || occ_channel > 3) {
+ fprintf(stderr, "occ-channel out of range 0 <= c <= 3\n");
+ exit(1);
+ }
+ break;
+ case 'h':
+ print_usage(0);
+ break;
+ case 'v':
+ printf("xscom utils version %s\n", version);
+ exit(0);
+ case 'f':
+ filename = optarg;
+ break;
+ case 'l':
+ length = strtoul(optarg, NULL, 0);
+ length = (length + 7) & ~0x7; /* round up to an eight byte interval */
+ break;
+ default:
+ exit(1);
+ }
+ }
+
+ if (addr == -1ull) {
+ fprintf(stderr, "Invalid or missing address\n");
+ print_usage(1);
+ }
+
+ def_chip = xscom_init();
+ if (def_chip == 0xffffffff) {
+ fprintf(stderr, "No valid XSCOM chip found\n");
+ exit(1);
+ }
+ if (chip_id == 0xffffffff)
+ chip_id = def_chip;
+
+ if (filename) {
+ f = fopen(filename, "wb");
+ if (!f) {
+ fprintf(stderr, "unable to open %s for writing\n", filename);
+ exit(1);
+ }
+ }
+
+ rc = 0;
+ while (length) {
+ rc = sram_read(chip_id, occ_channel, addr, &val);
+ if (rc)
+ break;
+
+ if (f) {
+ int i;
+
+ /* make sure we write it out big endian */
+ for (i = 1; i <= 8; i++)
+ fputc((val >> (64 - i * 8)) & 0xff, f);
+ } else {
+ printf("OCC%d: %" PRIx64 "\n", occ_channel, val);
+ }
+
+ length -= 8;
+ addr += 8;
+ }
+
+ if (rc) {
+ fprintf(stderr,"Error %d reading XSCOM\n", rc);
+ exit(1);
+ }
+ return 0;
+}
diff --git a/roms/skiboot/external/xscom-utils/putscom.1 b/roms/skiboot/external/xscom-utils/putscom.1
new file mode 100644
index 000000000..9c329fc27
--- /dev/null
+++ b/roms/skiboot/external/xscom-utils/putscom.1
@@ -0,0 +1,18 @@
+.TH XSCOM "1" "September 2016"
+.SH NAME
+putscom \- part of xscom utils
+.SH SYNOPIS
+.TP
+\fBputscom\fP [\-c | \-\-chip \fIchip\-id\fP] \fIaddr\fP \fIvalue\fP
+.TP
+\fBputscom\fP [\-v | \-\-version]
+.SH DESCRIPTION
+\fBputscom\fP utility provides an interface to modify the
+registers of the different chipsets of an OpenPower system.
+.SS Options
+.TP
+\fB\-c|\-\-chip-id\fP \fIchip\-id\fP
+Specify chipset where to modify register at \fIaddr\fP with \fIvalue\fP
+.TP
+\fB\-v|\-\-version\fP
+Display version of the tool
diff --git a/roms/skiboot/external/xscom-utils/putscom.c b/roms/skiboot/external/xscom-utils/putscom.c
new file mode 100644
index 000000000..b942eeb58
--- /dev/null
+++ b/roms/skiboot/external/xscom-utils/putscom.c
@@ -0,0 +1,115 @@
+// SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
+/*
+ * getscom
+ *
+ * Copyright 2014-2017 IBM Corp.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <getopt.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include <inttypes.h>
+
+#include "xscom.h"
+
+static void print_usage(int code)
+{
+ printf("usage: putscom [-c|--chip chip-id] [-b|--list-bits] addr value\n");
+ printf(" putscom -v|--version\n");
+ printf("\n");
+ printf(" NB: --list-bits shows which PPC bits are set\n");
+ exit(code);
+ exit(code);
+}
+
+extern const char version[];
+
+int main(int argc, char *argv[])
+{
+ uint64_t val = -1ull, addr = -1ull;
+ uint32_t def_chip, chip_id = 0xffffffff;
+ bool got_addr = false, got_val = false;
+ bool list_bits = false;
+ int rc;
+
+ while(1) {
+ static struct option long_opts[] = {
+ {"chip", required_argument, NULL, 'c'},
+ {"help", no_argument, NULL, 'h'},
+ {"version", no_argument, NULL, 'v'},
+ };
+ int c, oidx = 0;
+
+ c = getopt_long(argc, argv, "-c:bhv", long_opts, &oidx);
+ if (c == EOF)
+ break;
+ switch(c) {
+ case 1:
+ if (!got_addr) {
+ addr = strtoull(optarg, NULL, 16);
+ got_addr = true;
+ break;
+ }
+ val = strtoull(optarg, NULL, 16);
+ got_val = true;
+ break;
+ case 'c':
+ chip_id = strtoul(optarg, NULL, 16);
+ break;
+ case 'b':
+ list_bits = true;
+ break;
+ case 'v':
+ printf("xscom utils version %s\n", version);
+ exit(0);
+ case 'h':
+ print_usage(0);
+ break;
+ default:
+ exit(1);
+ }
+ }
+
+ if (!got_addr || !got_val) {
+ fprintf(stderr, "Invalid or missing address/value\n");
+ print_usage(1);
+ }
+
+ def_chip = xscom_init();
+ if (def_chip == 0xffffffff) {
+ fprintf(stderr, "No valid XSCOM chip found\n");
+ exit(1);
+ }
+ if (chip_id == 0xffffffff)
+ chip_id = def_chip;
+
+ rc = xscom_write(chip_id, addr, val);
+ if (rc) {
+ fprintf(stderr,"Error %d writing XSCOM\n", rc);
+ exit(1);
+ }
+ if (xscom_readable(addr)) {
+ rc = xscom_read(chip_id, addr, &val);
+ if (rc) {
+ fprintf(stderr,"Error %d reading XSCOM\n", rc);
+ exit(1);
+ }
+ }
+
+ printf("%016" PRIx64, val);
+ if (list_bits) {
+ int i;
+
+ printf(" - set: ");
+
+ for (i = 0; i < 64; i++)
+ if (val & PPC_BIT(i))
+ printf("%d ", i);
+ }
+
+ putchar('\n');
+ return 0;
+}
+
diff --git a/roms/skiboot/external/xscom-utils/sram.c b/roms/skiboot/external/xscom-utils/sram.c
new file mode 100644
index 000000000..efe08d8e7
--- /dev/null
+++ b/roms/skiboot/external/xscom-utils/sram.c
@@ -0,0 +1,139 @@
+// SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
+/* Copyright 2014-2019 IBM Corp. */
+
+#include <stdint.h>
+#include <stdio.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <time.h>
+
+#include "xscom.h"
+
+#define DBG(fmt...) do { if (verbose) printf(fmt); } while(0)
+#define ERR(fmt...) do { fprintf(stderr, fmt); } while(0)
+
+#define OCB_PIB_BASE_P8 0x0006B000
+#define OCB_PIB_BASE_P9 0x0006D000
+
+#define OCBCSR0 0x11
+#define OCBCSR0_AND 0x12
+#define OCBCSR0_OR 0x13
+#define OCB_STREAM_MODE PPC_BIT(4)
+#define OCB_STREAM_TYPE PPC_BIT(5)
+#define OCBAR0 0x10
+#define OCBDR0 0x15
+
+#define PVR_TYPE_P8E 0x004b /* Murano */
+#define PVR_TYPE_P8 0x004d /* Venice */
+#define PVR_TYPE_P8NVL 0x004c /* Naples */
+#define PVR_TYPE_P9 0x004e
+#define PVR_TYPE_P9P 0x004f /* Axone */
+#define PVR_TYPE_P10 0x0080
+
+#ifdef __powerpc__
+static uint64_t get_xscom_base(void)
+{
+ unsigned int pvr;
+
+ asm volatile("mfpvr %0" : "=r" (pvr));
+
+ switch (pvr >> 16) {
+ case PVR_TYPE_P9:
+ case PVR_TYPE_P9P:
+ case PVR_TYPE_P10: /* P10 OCB_PIB OCC Control Register is same for P9 and P10 */
+ return OCB_PIB_BASE_P9;
+
+ case PVR_TYPE_P8E:
+ case PVR_TYPE_P8:
+ case PVR_TYPE_P8NVL:
+ return OCB_PIB_BASE_P8;
+ }
+
+ ERR("Unknown processor, exiting\n");
+ exit(1);
+ return 0;
+}
+#else
+/* Just so it compiles on x86 */
+static uint64_t get_xscom_base(void) { return 0; }
+#endif
+
+int sram_read(uint32_t chip_id, int chan, uint32_t addr, uint64_t *val)
+{
+ uint64_t sdat, base = get_xscom_base();
+ uint32_t coff = chan * 0x20;
+ int rc;
+
+ /* Read for debug purposes */
+ rc = xscom_read(chip_id, base + OCBCSR0 + coff, &sdat);
+ if (rc) {
+ ERR("xscom OCBCSR0 read error %d\n", rc);
+ return -1;
+ }
+
+ /* Create an AND mask to clear bit 4 and 5 and poke the AND register */
+ sdat = ~(OCB_STREAM_MODE | OCB_STREAM_TYPE);
+ rc = xscom_write(chip_id, base + OCBCSR0_AND + coff, sdat);
+ if (rc) {
+ ERR("xscom OCBCSR0_AND write error %d\n", rc);
+ return -1;
+ }
+
+ sdat = ((uint64_t)addr) << 32;
+ rc = xscom_write(chip_id, base + OCBAR0 + coff, sdat);
+ if (rc) {
+ ERR("xscom OCBAR0 write error %d\n", rc);
+ return -1;
+ }
+
+ rc = xscom_read(chip_id, base + OCBDR0 + coff, val);
+ if (rc) {
+ ERR("xscom OCBDR0 read error %d\n", rc);
+ return -1;
+ }
+ return 0;
+}
+
+int sram_write(uint32_t chip_id, int chan, uint32_t addr, uint64_t val)
+{
+ uint64_t sdat, base = get_xscom_base();
+ uint32_t coff = chan * 0x20;
+ int rc;
+
+#if 0
+ if (dummy) {
+ printf("[dummy] write chip %d OCC sram 0x%08x = %016lx\n",
+ chip_id, addr, val);
+ return 0;
+ }
+#endif
+
+ /* Read for debug purposes */
+ rc = xscom_read(chip_id, base + OCBCSR0 + coff, &sdat);
+ if (rc) {
+ ERR("xscom OCBCSR0 read error %d\n", rc);
+ return -1;
+ }
+
+ /* Create an AND mask to clear bit 4 and 5 and poke the AND register */
+ sdat = ~(OCB_STREAM_MODE | OCB_STREAM_TYPE);
+ rc = xscom_write(chip_id, base + OCBCSR0_AND + coff, sdat);
+ if (rc) {
+ ERR("xscom OCBCSR0_AND write error %d\n", rc);
+ return -1;
+ }
+
+ sdat = ((uint64_t)addr) << 32;
+ rc = xscom_write(chip_id, base + OCBAR0 + coff, sdat);
+ if (rc) {
+ ERR("xscom OCBAR0 write error %d\n", rc);
+ return -1;
+ }
+
+ rc = xscom_write(chip_id, base + OCBDR0 + coff, val);
+ if (rc) {
+ ERR("xscom OCBDR0 write error %d\n", rc);
+ return -1;
+ }
+ return 0;
+}
diff --git a/roms/skiboot/external/xscom-utils/sram.h b/roms/skiboot/external/xscom-utils/sram.h
new file mode 100644
index 000000000..75d9155c4
--- /dev/null
+++ b/roms/skiboot/external/xscom-utils/sram.h
@@ -0,0 +1,14 @@
+// SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
+/* Copyright 2014-2016 IBM Corp. */
+
+#ifndef __SRAM_H
+#define __SRAM_H
+
+#include <stdint.h>
+
+extern int sram_read(uint32_t chip_id, int chan, uint64_t addr, uint64_t *val);
+extern int sram_write(uint32_t chip_id, int chan, uint64_t addr, uint64_t val);
+
+extern void sram_for_each_chip(void (*cb)(uint32_t chip_id));
+
+#endif /* __SRAM_H */
diff --git a/roms/skiboot/external/xscom-utils/xscom.c b/roms/skiboot/external/xscom-utils/xscom.c
new file mode 100644
index 000000000..031f9e193
--- /dev/null
+++ b/roms/skiboot/external/xscom-utils/xscom.c
@@ -0,0 +1,206 @@
+// SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
+/*
+ * Do XSCOMs through linux debugfs interface
+ *
+ * Copyright 2014-2017 IBM Corp.
+ */
+
+#define _LARGEFILE64_SOURCE
+#include <sys/mman.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include <dirent.h>
+#include <assert.h>
+#include <ctype.h>
+
+#include "xscom.h"
+
+#define XSCOM_BASE_PATH "/sys/kernel/debug/powerpc/scom"
+
+struct xscom_chip {
+ struct xscom_chip *next;
+ uint32_t chip_id;
+ int fd;
+};
+static struct xscom_chip *xscom_chips;
+
+void xscom_for_each_chip(void (*cb)(uint32_t chip_id))
+{
+ struct xscom_chip *c;
+
+ for (c = xscom_chips; c; c = c->next)
+ cb(c->chip_id);
+}
+
+static uint32_t xscom_add_chip(const char *base_path, const char *dname)
+{
+ char nbuf[strlen(base_path) + strlen(dname) + 16];
+ struct xscom_chip *chip;
+ int fd;
+
+ snprintf(nbuf, sizeof(nbuf), "%s/%s/access", base_path, dname);
+ fd = open(nbuf, O_RDWR);
+ if (fd < 0) {
+ perror("Failed to open SCOM access file");
+ exit(1);
+ }
+
+ chip = malloc(sizeof(*chip));
+ assert(chip);
+ memset(chip, 0, sizeof(*chip));
+ chip->fd = fd;
+ chip->chip_id = strtoul(dname, NULL, 16);
+ chip->next = xscom_chips;
+ xscom_chips = chip;
+
+ return chip->chip_id;
+}
+
+static bool xscom_check_dirname(const char *n)
+{
+ while(*n) {
+ char c = toupper(*(n++));
+
+ if ((c < 'A' || c > 'Z') &&
+ (c < '0' || c > '9'))
+ return false;
+ }
+ return true;
+}
+
+static uint32_t xscom_scan_chips(const char *base_path)
+{
+ int i, nfiles;
+ struct dirent **filelist;
+ uint32_t lower = 0xffffffff;
+
+ nfiles = scandir(base_path, &filelist, NULL, alphasort);
+ if (nfiles < 0) {
+ perror("Error accessing sysfs scom directory");
+ exit(1);
+ }
+ if (nfiles == 0) {
+ fprintf(stderr, "No SCOM dir found in sysfs\n");
+ exit(1);
+ }
+
+ for (i = 0; i < nfiles; i++) {
+ struct dirent *d = filelist[i];
+ uint32_t id;
+
+ if (d->d_type != DT_DIR)
+ continue;
+ if (!xscom_check_dirname(d->d_name))
+ continue;
+ id = xscom_add_chip(base_path, d->d_name);
+ if (id < lower)
+ lower = id;
+ free(d);
+ }
+
+ free(filelist);
+ return lower;
+}
+
+static struct xscom_chip *xscom_find_chip(uint32_t chip_id)
+{
+ struct xscom_chip *c;
+
+ for (c = xscom_chips; c; c = c->next)
+ if (c->chip_id == chip_id)
+ return c;
+ return NULL;
+}
+
+static uint64_t xscom_mangle_addr(uint64_t addr)
+{
+ uint64_t tmp;
+
+ /*
+ * Shift the top 4 bits (indirect mode) down by 4 bits so we
+ * don't lose going through the debugfs interfaces.
+ */
+ tmp = (addr & 0xf000000000000000) >> 4;
+ addr &= 0x00ffffffffffffff;
+ addr |= tmp;
+
+ /* Shift up by 3 for debugfs */
+ return addr << 3;
+}
+
+int xscom_read(uint32_t chip_id, uint64_t addr, uint64_t *val)
+{
+ struct xscom_chip *c = xscom_find_chip(chip_id);
+ int rc;
+
+ if (!c)
+ return -ENODEV;
+ addr = xscom_mangle_addr(addr);
+ lseek64(c->fd, addr, SEEK_SET);
+ rc = read(c->fd, val, 8);
+ if (rc < 0)
+ return -errno;
+ if (rc != 8)
+ return -EIO;
+ return 0;
+}
+
+int xscom_write(uint32_t chip_id, uint64_t addr, uint64_t val)
+{
+ struct xscom_chip *c = xscom_find_chip(chip_id);
+ int rc;
+
+ if (!c)
+ return -ENODEV;
+ addr = xscom_mangle_addr(addr);
+ lseek64(c->fd, addr, SEEK_SET);
+ rc = write(c->fd, &val, 8);
+ if (rc < 0)
+ return -errno;
+ if (rc != 8)
+ return -EIO;
+ return 0;
+}
+
+int xscom_read_ex(uint32_t ex_target_id, uint64_t addr, uint64_t *val)
+{
+ uint32_t chip_id = ex_target_id >> 4;;
+
+ addr |= (ex_target_id & 0xf) << 24;
+
+ /* XXX TODO: Special wakeup ? */
+
+ return xscom_read(chip_id, addr, val);
+}
+
+int xscom_write_ex(uint32_t ex_target_id, uint64_t addr, uint64_t val)
+{
+ uint32_t chip_id = ex_target_id >> 4;;
+
+ addr |= (ex_target_id & 0xf) << 24;
+
+ /* XXX TODO: Special wakeup ? */
+
+ return xscom_write(chip_id, addr, val);
+}
+
+bool xscom_readable(uint64_t addr)
+{
+ /* Top nibble 9 indicates form 1 indirect, which is write only */
+ if (((addr >> 60) & 0xf) == 9)
+ return false;
+ return true;
+}
+
+uint32_t xscom_init(void)
+{
+ return xscom_scan_chips(XSCOM_BASE_PATH);
+}
diff --git a/roms/skiboot/external/xscom-utils/xscom.h b/roms/skiboot/external/xscom-utils/xscom.h
new file mode 100644
index 000000000..05b8f543b
--- /dev/null
+++ b/roms/skiboot/external/xscom-utils/xscom.h
@@ -0,0 +1,26 @@
+// SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
+/* Copyright 2014-2017 IBM Corp.
+ */
+
+#ifndef __XSCOM_H
+#define __XSCOM_H
+
+#include <stdint.h>
+
+extern int xscom_read(uint32_t chip_id, uint64_t addr, uint64_t *val);
+extern int xscom_write(uint32_t chip_id, uint64_t addr, uint64_t val);
+
+extern int xscom_read_ex(uint32_t ex_target_id, uint64_t addr, uint64_t *val);
+extern int xscom_write_ex(uint32_t ex_target_id, uint64_t addr, uint64_t val);
+
+extern void xscom_for_each_chip(void (*cb)(uint32_t chip_id));
+
+extern bool xscom_readable(uint64_t addr);
+
+extern uint32_t xscom_init(void);
+
+#ifndef PPC_BIT
+#define PPC_BIT(bit) (0x8000000000000000UL >> (bit))
+#endif
+
+#endif /* __XSCOM_H */