summaryrefslogtreecommitdiff
path: root/gxp-debugfs.c
diff options
context:
space:
mode:
authorJohn Scheible <johnscheible@google.com>2021-10-26 13:45:19 -0700
committerJohn Scheible <johnscheible@google.com>2021-10-28 16:14:12 -0700
commitde16475969ca7dfaecf7144ece32b929cf193861 (patch)
tree962335a74133193541bf8c398a7cdf445f79a610 /gxp-debugfs.c
parent497cbdab5ea4f505beac7bb6d686bb4c3c504e8c (diff)
downloadgs201-de16475969ca7dfaecf7144ece32b929cf193861.tar.gz
gxp: First import from development branch
Squash at commit 48fe5786f1779890538d14f709b26063698c3711 Signed-off-by: John Scheible <johnscheible@google.com> Change-Id: I208434dddde40c08b9fc4d5da072ba10541992a2
Diffstat (limited to 'gxp-debugfs.c')
-rw-r--r--gxp-debugfs.c220
1 files changed, 220 insertions, 0 deletions
diff --git a/gxp-debugfs.c b/gxp-debugfs.c
new file mode 100644
index 0000000..e8991ec
--- /dev/null
+++ b/gxp-debugfs.c
@@ -0,0 +1,220 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * GXP debugfs support.
+ *
+ * Copyright (C) 2021 Google LLC
+ */
+
+#include "gxp.h"
+#include "gxp-debug-dump.h"
+#include "gxp-debugfs.h"
+#include "gxp-firmware.h"
+#include "gxp-firmware-data.h"
+#include "gxp-internal.h"
+#include "gxp-lpm.h"
+#include "gxp-mailbox.h"
+#include "gxp-vd.h"
+
+static int gxp_debugfs_lpm_test(void *data, u64 val)
+{
+ struct gxp_dev *gxp = (struct gxp_dev *) data;
+
+ dev_info(gxp->dev, "%llu\n", val);
+
+ return 0;
+}
+DEFINE_DEBUGFS_ATTRIBUTE(gxp_lpm_test_fops, NULL, gxp_debugfs_lpm_test,
+ "%llu\n");
+
+static int gxp_debugfs_mailbox(void *data, u64 val)
+{
+ int core;
+ struct gxp_command cmd;
+ struct gxp_response resp;
+ struct gxp_dev *gxp = (struct gxp_dev *)data;
+
+ core = val / 1000;
+ if (core >= GXP_NUM_CORES) {
+ dev_notice(gxp->dev,
+ "Mailbox for core %d doesn't exist.\n", core);
+ return -EINVAL;
+ }
+
+ if (gxp->mailbox_mgr == NULL ||
+ gxp->mailbox_mgr->mailboxes[core] == NULL) {
+ dev_notice(gxp->dev,
+ "Unable to send mailbox command -- mailbox %d not ready\n",
+ core);
+ return -EINVAL;
+ }
+
+ cmd.code = (u16) val;
+ cmd.priority = 0;
+ cmd.buffer_descriptor.address = 0;
+ cmd.buffer_descriptor.size = 0;
+ cmd.buffer_descriptor.flags = 0;
+
+ gxp_mailbox_execute_cmd(gxp->mailbox_mgr->mailboxes[core], &cmd, &resp);
+
+ dev_info(gxp->dev,
+ "Mailbox Command Sent: cmd.code=%d, resp.status=%d, resp.retval=%d\n",
+ cmd.code, resp.status, resp.retval);
+ return 0;
+}
+DEFINE_DEBUGFS_ATTRIBUTE(gxp_mailbox_fops, NULL, gxp_debugfs_mailbox, "%llu\n");
+
+static int gxp_debugfs_pingpong(void *data, u64 val)
+{
+ int core;
+ struct gxp_command cmd;
+ struct gxp_response resp;
+ struct gxp_dev *gxp = (struct gxp_dev *)data;
+
+ core = val / 1000;
+ if (core >= GXP_NUM_CORES) {
+ dev_notice(gxp->dev,
+ "Mailbox for core %d doesn't exist.\n", core);
+ return -EINVAL;
+ }
+
+ if (gxp->mailbox_mgr == NULL ||
+ gxp->mailbox_mgr->mailboxes[core] == NULL) {
+ dev_notice(
+ gxp->dev,
+ "Unable to send mailbox pingpong -- mailbox %d not ready\n",
+ core);
+ return -EINVAL;
+ }
+
+ cmd.code = GXP_MBOX_CODE_PINGPONG;
+ cmd.priority = 0;
+ cmd.buffer_descriptor.address = 0;
+ cmd.buffer_descriptor.size = 0;
+ cmd.buffer_descriptor.flags = (u32) val;
+
+ gxp_mailbox_execute_cmd(gxp->mailbox_mgr->mailboxes[core], &cmd, &resp);
+
+ dev_info(
+ gxp->dev,
+ "Mailbox Pingpong Sent to core %d: val=%d, resp.status=%d, resp.retval=%d\n",
+ core, cmd.buffer_descriptor.flags, resp.status, resp.retval);
+ return 0;
+}
+DEFINE_DEBUGFS_ATTRIBUTE(gxp_pingpong_fops, NULL, gxp_debugfs_pingpong,
+ "%llu\n");
+
+static int gxp_firmware_run_set(void *data, u64 val)
+{
+ struct gxp_dev *gxp = (struct gxp_dev *) data;
+ int ret = 0;
+
+ if (val) {
+ if (gxp->debugfs_client) {
+ dev_err(gxp->dev, "Firmware already running!\n");
+ return -EIO;
+ }
+
+ /*
+ * Cleanup any bad state or corruption the device might've
+ * caused
+ */
+ gxp_fw_data_destroy(gxp);
+ gxp_fw_data_init(gxp);
+
+ gxp->debugfs_client = gxp_client_create(gxp);
+ if (IS_ERR(gxp->debugfs_client)) {
+ dev_err(gxp->dev, "Failed to create client\n");
+ ret = PTR_ERR(gxp->debugfs_client);
+ gxp->debugfs_client = NULL;
+ return ret;
+ }
+
+ ret = gxp_vd_allocate(gxp->debugfs_client, GXP_NUM_CORES);
+ if (ret) {
+ dev_err(gxp->dev, "Failed to allocate VD\n");
+ gxp_client_destroy(gxp->debugfs_client);
+ gxp->debugfs_client = NULL;
+ return ret;
+ }
+ } else {
+ if (!gxp->debugfs_client) {
+ dev_err(gxp->dev, "Firmware not running!\n");
+ return -EIO;
+ }
+ gxp_client_destroy(gxp->debugfs_client);
+ gxp->debugfs_client = NULL;
+ }
+
+ return ret;
+}
+
+static int gxp_firmware_run_get(void *data, u64 *val)
+{
+ struct gxp_dev *gxp = (struct gxp_dev *) data;
+
+ *val = gxp->firmware_running;
+ return 0;
+}
+
+DEFINE_DEBUGFS_ATTRIBUTE(gxp_firmware_run_fops, gxp_firmware_run_get,
+ gxp_firmware_run_set, "%llx\n");
+
+static int gxp_blk_powerstate_set(void *data, u64 val)
+{
+ struct gxp_dev *gxp = (struct gxp_dev *)data;
+ int ret = 0;
+
+ if (val >= AUR_DVFS_MIN_STATE) {
+ ret = gxp_blk_set_state(gxp, val);
+ } else {
+ ret = -EINVAL;
+ dev_err(gxp->dev, "Incorrect state %llu\n", val);
+ }
+ return ret;
+}
+
+static int gxp_blk_powerstate_get(void *data, u64 *val)
+{
+ struct gxp_dev *gxp = (struct gxp_dev *)data;
+
+ *val = gxp_blk_get_state(gxp);
+ return 0;
+}
+
+DEFINE_DEBUGFS_ATTRIBUTE(gxp_blk_powerstate_fops, gxp_blk_powerstate_get,
+ gxp_blk_powerstate_set, "%llx\n");
+
+static int gxp_debugfs_coredump(void *data, u64 val)
+{
+ return gxp_debugfs_mailbox(data, GXP_MBOX_CODE_COREDUMP);
+}
+DEFINE_DEBUGFS_ATTRIBUTE(gxp_coredump_fops, NULL, gxp_debugfs_coredump,
+ "%llu\n");
+
+void gxp_create_debugfs(struct gxp_dev *gxp)
+{
+ gxp->d_entry = debugfs_create_dir("gxp", NULL);
+ if (IS_ERR_OR_NULL(gxp->d_entry))
+ return;
+
+ debugfs_create_file("lpm_test", 0200, gxp->d_entry, gxp,
+ &gxp_lpm_test_fops);
+ debugfs_create_file("mailbox", 0200, gxp->d_entry, gxp,
+ &gxp_mailbox_fops);
+ debugfs_create_file("pingpong", 0200, gxp->d_entry, gxp,
+ &gxp_pingpong_fops);
+ debugfs_create_file("firmware_run", 0600, gxp->d_entry, gxp,
+ &gxp_firmware_run_fops);
+ debugfs_create_file("blk_powerstate", 0600, gxp->d_entry, gxp,
+ &gxp_blk_powerstate_fops);
+ debugfs_create_file("coredump", 0200, gxp->d_entry, gxp,
+ &gxp_coredump_fops);
+}
+
+void gxp_remove_debugfs(struct gxp_dev *gxp)
+{
+ if (gxp->debugfs_client)
+ gxp_client_destroy(gxp->debugfs_client);
+
+ debugfs_remove_recursive(gxp->d_entry);
+}