[Pdbg] [PATCH v2 2/4] libpdbg: use i2ctools lib
Rashmica Gupta
rashmica.g at gmail.com
Thu Apr 18 11:26:56 AEST 2019
This should do the same thing as the i2ctools i2cget cmd.
Signed-off-by: Rashmica Gupta <rashmica.g at gmail.com>
---
Makefile.am | 6 ++++
configure.ac | 5 +++
libpdbg/i2cm.c | 83 +++++++++++++++++++++++++++++++++++++++++++++++
libpdbg/libpdbg.h | 3 ++
libpdbg/target.c | 11 +++++++
libpdbg/target.h | 9 +++++
p9-i2c.dts.m4 | 21 ++++++++++++
p9-kernel.dts.m4 | 8 +++++
src/i2c.c | 53 ++++++++++++++++++++++++++++++
src/main.c | 5 +--
10 files changed, 202 insertions(+), 2 deletions(-)
create mode 100644 libpdbg/i2cm.c
create mode 100644 p9-i2c.dts.m4
create mode 100644 src/i2c.c
diff --git a/Makefile.am b/Makefile.am
index d34cf20..1608fd4 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -75,6 +75,7 @@ pdbg_SOURCES = \
src/cfam.c \
src/htm.c \
src/htm.h \
+ src/i2c.c \
src/main.c \
src/main.h \
src/mem.c \
@@ -132,6 +133,10 @@ lib_LTLIBRARIES = libfdt.la libpdbg.la
libfdt_la_CFLAGS = -I$(top_srcdir)/libfdt
libpdbg_la_CFLAGS = -I$(top_srcdir)/libfdt -Wall -Werror
+if I2CLIB
+pdbg_LDADD += -li2c
+libpdbg_la_CFLAGS += -DENABLE_I2CLIB
+endif
libfdt_la_SOURCES = \
libfdt/fdt_addresses.c \
@@ -164,6 +169,7 @@ libpdbg_la_SOURCES = \
libpdbg/host.c \
libpdbg/htm.c \
libpdbg/i2c.c \
+ libpdbg/i2cm.c \
libpdbg/kernel.c \
libpdbg/libpdbg.c \
libpdbg/libpdbg.h \
diff --git a/configure.ac b/configure.ac
index a52e1ed..ae661d5 100644
--- a/configure.ac
+++ b/configure.ac
@@ -42,4 +42,9 @@ want_gdbserver=false,
want_gdbserver=true)
AM_CONDITIONAL([GDBSERVER], [test x$want_gdbserver = xtrue])
+AC_ARG_ENABLE(i2clib,
+AC_HELP_STRING([--enable-i2clib], [enables looking for the i2c lib]),
+want_i2clib=true,
+want_i2clib=false)
+AM_CONDITIONAL([I2CLIB], [test x$want_i2clib = xtrue])
AC_OUTPUT
diff --git a/libpdbg/i2cm.c b/libpdbg/i2cm.c
new file mode 100644
index 0000000..3e0218d
--- /dev/null
+++ b/libpdbg/i2cm.c
@@ -0,0 +1,83 @@
+/* Copyright 2019 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.
+ */
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <inttypes.h>
+#include <string.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <endian.h>
+#include <sys/ioctl.h>
+#include <linux/i2c-dev.h>
+
+#include "operations.h"
+#include "debug.h"
+
+#include <errno.h>
+#include <sys/param.h>
+#include <dirent.h>
+
+#ifdef ENABLE_I2CLIB
+#include <i2c/smbus.h>
+
+static int kernel_i2c_get(struct i2cbus *i2cbus, uint8_t addr, uint16_t size, uint8_t *data)
+{
+ int res = 0;
+ //fix this is smbus not i2cget
+
+ if (ioctl(i2cbus->i2c_fd, I2C_SLAVE, addr) < 0)
+ return -1;
+
+ res = i2c_smbus_read_byte_data(i2cbus->i2c_fd, 0);
+ PR_DEBUG("read %x from device %x\n", res, addr);
+ if (res >= 0) {
+ *data = (uint64_t)res;
+ return 0;
+ }
+ return -1;
+}
+
+static int i2cbus_probe(struct pdbg_target *target)
+{
+ int i2c_fd = 0;
+ int len;
+ char i2c_path[NAME_MAX];
+ struct i2cbus *i2cbus;
+
+ len = snprintf(i2c_path, NAME_MAX, "/dev/i2c-%i", target->index);
+ if (len >= NAME_MAX)
+ return -1;
+ i2c_fd = open(i2c_path, O_RDWR);
+ if (!i2c_fd)
+ return -1;
+
+ i2cbus = target_to_i2cbus(target);
+ i2cbus->i2c_fd = i2c_fd;
+ return 0;
+}
+
+static struct i2cbus i2c_bus = {
+ .target = {
+ .name = "I2C Bus",
+ .compatible = "ibm,power9-i2c-port",
+ .class = "i2c_bus",
+ .probe = i2cbus_probe,
+ },
+ .read = kernel_i2c_get,
+};
+DECLARE_HW_UNIT(i2c_bus);
+#endif
diff --git a/libpdbg/libpdbg.h b/libpdbg/libpdbg.h
index 4fad158..c09faa5 100644
--- a/libpdbg/libpdbg.h
+++ b/libpdbg/libpdbg.h
@@ -123,6 +123,9 @@ struct pdbg_target *pdbg_address_absolute(struct pdbg_target *target, uint64_t *
int fsi_read(struct pdbg_target *target, uint32_t addr, uint32_t *val);
int fsi_write(struct pdbg_target *target, uint32_t addr, uint32_t val);
+int i2c_read(struct pdbg_target *target, uint8_t addr, uint16_t size,
+ uint8_t *data);
+
int pib_read(struct pdbg_target *target, uint64_t addr, uint64_t *val);
int pib_write(struct pdbg_target *target, uint64_t addr, uint64_t val);
int pib_wait(struct pdbg_target *pib_dt, uint64_t addr, uint64_t mask, uint64_t data);
diff --git a/libpdbg/target.c b/libpdbg/target.c
index e678470..2366ed9 100644
--- a/libpdbg/target.c
+++ b/libpdbg/target.c
@@ -195,6 +195,17 @@ int opb_write(struct pdbg_target *opb_dt, uint32_t addr, uint32_t data)
return opb->write(opb, addr64, data);
}
+int i2c_read(struct pdbg_target *i2cm_dt, uint8_t addr, uint16_t size, uint8_t *data)
+{
+ struct i2cbus *i2cbus;
+ uint64_t addr64 = addr;
+
+ i2cm_dt = get_class_target_addr(i2cm_dt, "i2c_bus", &addr64);
+ i2cbus = target_to_i2cbus(i2cm_dt);
+
+ return i2cbus->read(i2cbus, addr, size, data);
+}
+
int fsi_read(struct pdbg_target *fsi_dt, uint32_t addr, uint32_t *data)
{
struct fsi *fsi;
diff --git a/libpdbg/target.h b/libpdbg/target.h
index 04897ed..814e59a 100644
--- a/libpdbg/target.h
+++ b/libpdbg/target.h
@@ -138,6 +138,15 @@ struct fsi {
};
#define target_to_fsi(x) container_of(x, struct fsi, target)
+struct i2cbus {
+ struct pdbg_target target;
+ int (*read)(struct i2cbus *, uint8_t, uint16_t, uint8_t *);
+ int (*write)(struct i2cbus *, uint8_t, uint16_t, uint8_t*);
+ int i2c_fd;
+};
+#define target_to_i2cbus(x) container_of(x, struct i2cbus, target)
+
+
struct core {
struct pdbg_target target;
bool release_spwkup;
diff --git a/p9-i2c.dts.m4 b/p9-i2c.dts.m4
new file mode 100644
index 0000000..d51dc83
--- /dev/null
+++ b/p9-i2c.dts.m4
@@ -0,0 +1,21 @@
+define(`I2CBUS', `i2c_bus@$1 {
+bus-frequency = <0x61a80>;
+compatible = "ibm,opal-i2c", "ibm,power8-i2c-port", "ibm,power9-i2c-port";
+index = <$1>;
+reg = <$1>;
+}')dnl
+
+I2CBUS(0);
+I2CBUS(1);
+I2CBUS(2);
+I2CBUS(3);
+I2CBUS(4);
+I2CBUS(5);
+I2CBUS(6);
+I2CBUS(7);
+I2CBUS(8);
+I2CBUS(9);
+I2CBUS(10);
+I2CBUS(11);
+I2CBUS(12);
+I2CBUS(13);
diff --git a/p9-kernel.dts.m4 b/p9-kernel.dts.m4
index 195be59..cc07682 100644
--- a/p9-kernel.dts.m4
+++ b/p9-kernel.dts.m4
@@ -22,6 +22,14 @@
include(p9-pib.dts.m4)dnl
};
+ i2cm at 1800 {
+ #address-cells = <0x1>;
+ #size-cells = <0x0>;
+ reg = <0x0 0x1800 0x400>;
+ compatible = "ibm,kernel-i2c-master";
+ include(p9-i2c.dts.m4)dnl
+ };
+
hmfsi at 100000 {
#address-cells = <0x2>;
#size-cells = <0x1>;
diff --git a/src/i2c.c b/src/i2c.c
new file mode 100644
index 0000000..5d1fc5b
--- /dev/null
+++ b/src/i2c.c
@@ -0,0 +1,53 @@
+/* Copyright 2019 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.
+ */
+
+#include <libpdbg.h>
+#include <inttypes.h>
+#include <stdlib.h>
+
+#include "main.h"
+#include "optcmd.h"
+#include "path.h"
+#include "target.h"
+#include "util.h"
+#include "debug.h"
+
+static int geti2c(uint8_t addr, uint16_t size)
+{
+ uint8_t *data = NULL;
+ struct pdbg_target *target, *selected = NULL;
+ int rc = 0;
+
+ data = malloc(size);
+ assert(data);
+
+ for_each_path_target_class("i2c_bus", target) {
+ if (pdbg_target_probe(target) != PDBG_TARGET_ENABLED)
+ continue;
+ selected = target;
+ rc = i2c_read(target, addr, size, data);
+ break;
+ }
+ if (selected == NULL)
+ return -1;
+ if (rc) {
+ PR_ERROR("Unable to read device.\n");
+ return rc;
+ }
+ hexdump(0, data, size, 1);
+ return 0;
+}
+OPTCMD_DEFINE_CMD_WITH_ARGS(geti2c, geti2c, (DATA8, DATA16));
diff --git a/src/main.c b/src/main.c
index d5f9385..3441d3c 100644
--- a/src/main.c
+++ b/src/main.c
@@ -93,7 +93,7 @@ extern struct optcmd_cmd
optcmd_threadstatus, optcmd_sreset, optcmd_regs, optcmd_probe,
optcmd_getmem, optcmd_putmem, optcmd_getmemio, optcmd_putmemio,
optcmd_getxer, optcmd_putxer, optcmd_getcr, optcmd_putcr,
- optcmd_gdbserver;
+ optcmd_gdbserver, optcmd_geti2c;
static struct optcmd_cmd *cmds[] = {
&optcmd_getscom, &optcmd_putscom, &optcmd_getcfam, &optcmd_putcfam,
@@ -103,7 +103,7 @@ static struct optcmd_cmd *cmds[] = {
&optcmd_threadstatus, &optcmd_sreset, &optcmd_regs, &optcmd_probe,
&optcmd_getmem, &optcmd_putmem, &optcmd_getmemio, &optcmd_putmemio,
&optcmd_getxer, &optcmd_putxer, &optcmd_getcr, &optcmd_putcr,
- &optcmd_gdbserver,
+ &optcmd_gdbserver, &optcmd_geti2c,
};
/* Purely for printing usage text. We could integrate printing argument and flag
@@ -145,6 +145,7 @@ static struct action actions[] = {
{ "sreset", "", "Reset" },
{ "regs", "[--backtrace]", "State (optionally display backtrace)" },
{ "gdbserver", "", "Start a gdb server" },
+ { "geti2c", "<device> <n>", "Read n bytes from specified device" },
};
static void print_usage(void)
--
2.17.2
More information about the Pdbg
mailing list