[Skiboot] [PATCH] external: Add a getsram command

Cédric Le Goater clg at fr.ibm.com
Tue Mar 8 20:37:00 AEDT 2016


The getsram command reads the OCC SRAM. This is useful for debug.

The code is totally inspired from the meltbox tool.

Signed-off-by: Cédric Le Goater <clg at fr.ibm.com>
---
 external/xscom-utils/Makefile  |    9 ++-
 external/xscom-utils/getsram.c |   97 +++++++++++++++++++++++++++++++++++++++
 external/xscom-utils/sram.c    |  100 +++++++++++++++++++++++++++++++++++++++++
 external/xscom-utils/sram.h    |   11 ++++
 4 files changed, 214 insertions(+), 3 deletions(-)
 create mode 100644 external/xscom-utils/getsram.c
 create mode 100644 external/xscom-utils/sram.c
 create mode 100644 external/xscom-utils/sram.h

Index: skiboot.git/external/xscom-utils/Makefile
===================================================================
--- skiboot.git.orig/external/xscom-utils/Makefile
+++ skiboot.git/external/xscom-utils/Makefile
@@ -1,17 +1,20 @@
-all: getscom putscom
+all: getscom putscom getsram
 
-VERSION=0.1
+VERSION=0.2
 CFLAGS=-O2 -g -Wall -m64 -DVERSION=$(VERSION)
 
 getscom: getscom.c xscom.c
 	$(CC) $(CFLAGS) -o $@ $^
 
+getsram: getsram.c xscom.c sram.c
+	$(CC) $(CFLAGS) -o $@ $^
+
 putscom: putscom.c xscom.c
 	$(CC) $(CFLAGS) -o $@ $^
 
 .PHONY: clean
 clean:
-	rm -rf getscom putscom
+	rm -rf getscom putscom getsram
 
 .PHONY: distclean
 distclean: clean
Index: skiboot.git/external/xscom-utils/getsram.c
===================================================================
--- /dev/null
+++ skiboot.git/external/xscom-utils/getsram.c
@@ -0,0 +1,97 @@
+#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(void)
+{
+	printf("usage: getsram [-c|--chip chip-id] addr\n");
+	printf("               [--occ-channel|n <chan>]\n");
+	printf("       getsram -v|--version\n");
+}
+
+#define VERSION_STR _str(VERSION)
+#define _str(s) __str(s)
+#define __str(s) #s
+
+int main(int argc, char *argv[])
+{
+	uint64_t val, addr = -1ull;
+	uint32_t def_chip, chip_id = 0xffffffff;
+	bool show_help = false;
+	bool show_version = false;
+	bool no_work = false;
+	int rc;
+	int occ_channel = 0;
+
+	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'},
+		};
+		int c, oidx = 0;
+
+		c = getopt_long(argc, argv, "-c:n:hlv", long_opts, &oidx);
+		if (c == EOF)
+			break;
+		switch(c) {
+		case 1:
+			addr = strtoull(optarg, NULL, 16);
+			break;
+		case 'c':
+			chip_id = strtoul(optarg, NULL, 0);
+			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':
+			show_help = true;
+			break;
+		case 'v':
+			show_version = true;
+			break;
+		default:
+			exit(1);
+		}
+	}
+
+	if (addr == -1ull)
+		no_work = true;
+	if (no_work && !show_version && !show_help) {
+		fprintf(stderr, "Invalid or missing address\n");
+		print_usage();
+		exit(1);
+	}
+	if (show_version)
+		printf("xscom utils version %s\n", VERSION_STR);
+	if (show_help)
+		print_usage();
+	if (no_work)
+		return 0;
+	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 = sram_read(chip_id, occ_channel, addr, &val);
+	if (rc) {
+		fprintf(stderr,"Error %d reading XSCOM\n", rc);
+		exit(1);
+	}
+	printf("OCC%d: %" PRIx64 "\n", occ_channel, val);
+	return 0;
+}
Index: skiboot.git/external/xscom-utils/sram.c
===================================================================
--- /dev/null
+++ skiboot.git/external/xscom-utils/sram.c
@@ -0,0 +1,100 @@
+#include <stdint.h>
+#include <stdio.h>
+#include <stdbool.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 PPC_BIT(bit)		(0x8000000000000000UL >> (bit))
+
+
+#define OCB_PIB_OCBCSR0_0x0006B011	0x0006B011
+#define OCB_PIB_OCBCSR0_ANDx0006B012	0x0006B012
+#define OCB_PIB_OCBCSR0_ORx0006B013	0x0006B013
+#define   OCB_STREAM_MODE			PPC_BIT(4)
+#define   OCB_STREAM_TYPE			PPC_BIT(5)
+#define OCB_PIB_OCBAR0_0x0006B010	0x0006B010
+#define OCB_PIB_OCBDR0_0x0006B015	0x0006B015
+
+int sram_read(uint32_t chip_id, int chan, uint32_t addr, uint64_t *val)
+{
+	uint32_t coff = chan * 0x20;
+	uint64_t sdat;
+	int rc;
+
+	/* Read for debug purposes */
+	rc = xscom_read(chip_id, OCB_PIB_OCBCSR0_0x0006B011 + coff, &sdat);
+	if (rc) {
+		ERR("xscom OCB_PIB_OCBCSR0_0x0006B011 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, OCB_PIB_OCBCSR0_ANDx0006B012 + coff, sdat);
+	if (rc) {
+		ERR("xscom OCB_PIB_OCBCSR0_ANDx0006B012 write error %d\n", rc);
+		return -1;
+	}
+
+	sdat = ((uint64_t)addr) << 32;
+	rc = xscom_write(chip_id, OCB_PIB_OCBAR0_0x0006B010 + coff, sdat);
+	if (rc) {
+		ERR("xscom OCB_PIB_OCBAR0_0x0006B010 write error %d\n", rc);
+		return -1;
+	}
+
+	rc = xscom_read(chip_id, OCB_PIB_OCBDR0_0x0006B015 + coff, val);
+	if (rc) {
+		ERR("xscom OCB_PIB_OCBAR0_0x0006B010 read error %d\n", rc);
+		return -1;
+	}
+	return 0;
+}
+
+int sram_write(uint32_t chip_id, int chan, uint32_t addr, uint64_t val)
+{
+	uint32_t coff = chan * 0x20;
+	uint64_t sdat;
+	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, OCB_PIB_OCBCSR0_0x0006B011 + coff, &sdat);
+	if (rc) {
+		ERR("xscom OCB_PIB_OCBCSR0_0x0006B011 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, OCB_PIB_OCBCSR0_ANDx0006B012 + coff, sdat);
+	if (rc) {
+		ERR("xscom OCB_PIB_OCBCSR0_ANDx0006B012 write error %d\n", rc);
+		return -1;
+	}
+
+	sdat = ((uint64_t)addr) << 32;
+	rc = xscom_write(chip_id, OCB_PIB_OCBAR0_0x0006B010 + coff, sdat);
+	if (rc) {
+		ERR("xscom OCB_PIB_OCBAR0_0x0006B010 write error %d\n", rc);
+		return -1;
+	}
+
+	rc = xscom_write(chip_id, OCB_PIB_OCBDR0_0x0006B015 + coff, val);
+	if (rc) {
+		ERR("xscom OCB_PIB_OCBAR0_0x0006B010 write error %d\n", rc);
+		return -1;
+	}
+	return 0;
+}
Index: skiboot.git/external/xscom-utils/sram.h
===================================================================
--- /dev/null
+++ skiboot.git/external/xscom-utils/sram.h
@@ -0,0 +1,11 @@
+#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 */



More information about the Skiboot mailing list