external/xscom-utils: Add python library for xscom access

Message ID 1528374076-26183-1-git-send-email-maddy@linux.vnet.ibm.com
State Accepted
Headers show
Series
  • external/xscom-utils: Add python library for xscom access
Related show

Commit Message

Madhavan Srinivasan June 7, 2018, 12:21 p.m.
Patch adds a simple python library module for xscom access.
It directly manipulate the '/access' file for scom read
and write from debugfs 'scom' directory.

Example on how to generate a getscom using this module:

	#!/usr/bin/python

	from adu_scoms import *
	getscom = GetSCom()
	getscom.parse_args()
	getscom.run_command()

Sample output for above getscom.py:

# ./getscom.py -l
Chip ID  | Rev   | Chip type
---------|-------|-----------
00000008 | DD2.0 | P9 (Nimbus) processor
00000000 | DD2.0 | P9 (Nimbus) processor

Signed-off-by: Madhavan Srinivasan <maddy@linux.vnet.ibm.com>
---
 external/xscom-utils/adu_scoms.py | 312 ++++++++++++++++++++++++++++++++++++++
 1 file changed, 312 insertions(+)
 create mode 100755 external/xscom-utils/adu_scoms.py

Comments

Stewart Smith June 19, 2018, 5:41 a.m. | #1
Madhavan Srinivasan <maddy@linux.vnet.ibm.com> writes:
> Patch adds a simple python library module for xscom access.
> It directly manipulate the '/access' file for scom read
> and write from debugfs 'scom' directory.
>
> Example on how to generate a getscom using this module:
>
> 	#!/usr/bin/python
>
> 	from adu_scoms import *
> 	getscom = GetSCom()
> 	getscom.parse_args()
> 	getscom.run_command()
>
> Sample output for above getscom.py:
>
> # ./getscom.py -l
> Chip ID  | Rev   | Chip type
> ---------|-------|-----------
> 00000008 | DD2.0 | P9 (Nimbus) processor
> 00000000 | DD2.0 | P9 (Nimbus) processor
>
> Signed-off-by: Madhavan Srinivasan <maddy@linux.vnet.ibm.com>
> ---
>  external/xscom-utils/adu_scoms.py | 312 ++++++++++++++++++++++++++++++++++++++
>  1 file changed, 312 insertions(+)
>  create mode 100755 external/xscom-utils/adu_scoms.py

Merged to master as of 28ba76c32ea1521625984ec3d54a437947628c91

Patch

diff --git a/external/xscom-utils/adu_scoms.py b/external/xscom-utils/adu_scoms.py
new file mode 100755
index 000000000000..eab5bbea69b0
--- /dev/null
+++ b/external/xscom-utils/adu_scoms.py
@@ -0,0 +1,312 @@ 
+#!/usr/bin/python
+
+# Python library for in-band SCom access
+# (based on xscom-utils from OPAL firmware)
+#
+# Copyright 2018 IBM Corp.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#	http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+# implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+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 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 not self.key_val_bin.has_key(chip_id):
+			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 not self.key_val_bin.has_key(chip_id):
+			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 not self.key_val_bin.has_key(chip_id):
+			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 == 0xf9:
+			name = "P7 processor"
+		elif id == 0xe8:
+			name = "P7+ processor"
+		elif 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 == 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)
+