]> git.kernelconcepts.de Git - karo-tx-uboot.git/commitdiff
cmd: add support for Qualcomm SPMI bus access
authorLothar Waßmann <LW@KARO-electronics.de>
Mon, 13 Mar 2017 15:03:57 +0000 (16:03 +0100)
committerLothar Waßmann <LW@KARO-electronics.de>
Tue, 14 Mar 2017 16:38:50 +0000 (17:38 +0100)
This patch adds an 'spmi' command for low level access to the SPMI bus
similar to the 'i2c' command from which it was inspired.

cmd/Kconfig
cmd/Makefile
cmd/spmi.c [new file with mode: 0644]

index 86554ea36229098581f0c5dd22a40e9ea8090cf3..17808de716d447145cfa7209a6ed4102af651308 100644 (file)
@@ -388,7 +388,7 @@ config CMD_SF
          SPI Flash support
 
 config CMD_SPI
-       bool "sspi"
+       bool "spi"
        help
          SPI utility command.
 
@@ -431,6 +431,11 @@ config CMD_GPIO
        help
          GPIO support.
 
+config CMD_SPMI
+       bool "spmi"
+       help
+         SPMI bus utility command.
+
 endmenu
 
 
index 81b98ee0d751005dc376534837596ee2206beefa..5d911f50f8237909ceece5e0fdda618ce33e4e18 100644 (file)
@@ -121,6 +121,7 @@ obj-$(CONFIG_CMD_SETEXPR) += setexpr.o
 obj-$(CONFIG_CMD_SOFTSWITCH) += softswitch.o
 obj-$(CONFIG_CMD_SPI) += spi.o
 obj-$(CONFIG_CMD_SPIBOOTLDR) += spibootldr.o
+obj-$(CONFIG_CMD_SPMI) += spmi.o
 obj-$(CONFIG_CMD_STRINGS) += strings.o
 obj-$(CONFIG_CMD_TERMINAL) += terminal.o
 obj-$(CONFIG_CMD_TIME) += time.o
diff --git a/cmd/spmi.c b/cmd/spmi.c
new file mode 100644 (file)
index 0000000..fd80b3a
--- /dev/null
@@ -0,0 +1,185 @@
+/*
+ * (C) Copyright 2017 Lothar Waßmann <LW@KARO-electronics.de>
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ *
+ * based on: cmd/i2c.c
+ *   (C) Copyright 2009
+ *   Sergey Kubushyn, himself, ksi@koi8.net
+ *
+ *   (C) Copyright 2001
+ *   Gerald Van Baren, Custom IDEAS, vanbaren@cideas.com.
+ */
+
+#include <common.h>
+#include <cli.h>
+#include <command.h>
+#include <console.h>
+#include <dm.h>
+#include <environment.h>
+#include <errno.h>
+#include <malloc.h>
+#include <asm/byteorder.h>
+#include <linux/compiler.h>
+#include <spmi/spmi.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+enum spmi_err_op {
+       SPMI_ERR_READ,
+       SPMI_ERR_WRITE,
+};
+
+static int spmi_report_err(int ret, enum spmi_err_op op)
+{
+       printf("Error %s the chip: %d\n",
+              op == SPMI_ERR_READ ? "reading" : "writing", ret);
+
+       return CMD_RET_FAILURE;
+}
+
+/**
+ * do_spmi_read() - Handle the "spmi read" command-line command
+ * @cmdtp:     Command data struct pointer
+ * @flag:      Command flag
+ * @argc:      Command-line argument count
+ * @argv:      Array of command-line arguments
+ *
+ * Returns zero on success, CMD_RET_USAGE in case of misuse and negative
+ * on error.
+ *
+ * Syntax:
+ *     spmi read {spmi_chip} {devaddr}{.0, .1, .2} {len} {memaddr}
+ */
+static int do_spmi_read(cmd_tbl_t *cmdtp, int flag, int argc,
+                       char *const argv[])
+{
+       uint sid, pid, reg;
+       int ret;
+       struct udevice *dev;
+
+       if (argc != 4)
+               return cmd_usage(cmdtp);
+
+       ret = uclass_get_device_by_name(UCLASS_SPMI, "spmi", &dev);
+       if (ret) {
+               printf("Failed to get SPMI bus: %d\n", ret);
+               return CMD_RET_FAILURE;
+       }
+
+       /*
+        * SPMI chip address
+        */
+       sid = simple_strtoul(argv[1], NULL, 16);
+
+       /*
+        * SPMI data address within the chip.  This can be 1 or
+        * 2 bytes long.  Some day it might be 3 bytes long :-).
+        */
+       pid = simple_strtoul(argv[2], NULL, 16);
+       reg = simple_strtoul(argv[3], NULL, 16);
+
+       ret = spmi_reg_read(dev, sid, pid, reg);
+       if (ret < 0)
+               return spmi_report_err(ret, SPMI_ERR_READ);
+
+       printf("%02x\n", ret);
+       return CMD_RET_SUCCESS;
+}
+
+static int do_spmi_write(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
+{
+       uint sid, pid, reg;
+       uint val;
+       int ret;
+       struct udevice *dev;
+
+       if (argc != 5)
+               return cmd_usage(cmdtp);
+
+       ret = uclass_get_device_by_name(UCLASS_SPMI, "spmi", &dev);
+       if (ret) {
+               printf("Failed to get SPMI bus: %d\n", ret);
+               return CMD_RET_FAILURE;
+       }
+
+       /*
+        * SPMI chip address
+        */
+       sid = simple_strtoul(argv[1], NULL, 16);
+       pid = simple_strtoul(argv[2], NULL, 16);
+       reg = simple_strtoul(argv[3], NULL, 16);
+       val = simple_strtoul(argv[4], NULL, 16);
+       if (val > 255) {
+               printf("Value %08x out of range [0..255]\n", val);
+               return CMD_RET_FAILURE;
+       }
+
+       ret = spmi_reg_write(dev, sid, pid, reg, val);
+       if (ret)
+               return spmi_report_err(ret, SPMI_ERR_WRITE);
+
+       return CMD_RET_SUCCESS;
+}
+
+static cmd_tbl_t cmd_spmi_sub[] = {
+       U_BOOT_CMD_MKENT(read, 4, 1, do_spmi_read, "", ""),
+       U_BOOT_CMD_MKENT(write, 5, 0, do_spmi_write, "", ""),
+};
+
+static __maybe_unused void spmi_reloc(void)
+{
+       static int relocated;
+
+       if (!relocated) {
+               fixup_cmdtable(cmd_spmi_sub, ARRAY_SIZE(cmd_spmi_sub));
+               relocated = 1;
+       };
+}
+
+/**
+ * do_spmi() - Handle the "spmi" command-line command
+ * @cmdtp:     Command data struct pointer
+ * @flag:      Command flag
+ * @argc:      Command-line argument count
+ * @argv:      Array of command-line arguments
+ *
+ * Returns zero on success, CMD_RET_USAGE in case of misuse and negative
+ * on error.
+ */
+static int do_spmi(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
+{
+       cmd_tbl_t *c;
+
+#ifdef CONFIG_NEEDS_MANUAL_RELOC
+       spmi_reloc();
+#endif
+
+       if (argc < 2)
+               return CMD_RET_USAGE;
+
+       /* Strip off leading 'spmi' command argument */
+       argc--;
+       argv++;
+
+       c = find_cmd_tbl(argv[0], cmd_spmi_sub, ARRAY_SIZE(cmd_spmi_sub));
+
+       if (c)
+               return c->cmd(cmdtp, flag, argc, argv);
+       else
+               printf("subcommand '%s' not found\n", argv[0]);
+       return CMD_RET_USAGE;
+}
+
+#ifdef CONFIG_SYS_LONGHELP
+static char spmi_help_text[] =
+       "\tspmi read <sid> <pid> <reg>         - read register <reg> of peripheral <pid> on slave <sid>\n"
+       "\tspmi write <sid> <pid> <reg> <val>  - write <val> to register <reg> of peripheral <pid> on slave <sid>\n"
+       ;
+#endif
+
+U_BOOT_CMD(
+       spmi, 6, 1, do_spmi,
+       "SPMI sub-system",
+       spmi_help_text
+);