Merge "drivers: qcom: cmd-db: Dump resource data via debugfs" into msm-4.9
diff --git a/drivers/soc/qcom/cmd-db.c b/drivers/soc/qcom/cmd-db.c
index 5cc04c0..252bd21 100644
--- a/drivers/soc/qcom/cmd-db.c
+++ b/drivers/soc/qcom/cmd-db.c
@@ -19,6 +19,9 @@
#include <linux/of_address.h>
#include <linux/of_platform.h>
#include <linux/kernel.h>
+#include <linux/debugfs.h>
+#include <linux/fs.h>
+#include <linux/seq_file.h>
#include <soc/qcom/cmd-db.h>
#define RESOURCE_ID_LEN 8
@@ -239,6 +242,108 @@ int cmd_db_get_slave_id(const char *resource_id)
return ret < 0 ? 0 : (ent.addr >> SLAVE_ID_SHIFT) & SLAVE_ID_MASK;
}
+static void *cmd_db_start(struct seq_file *m, loff_t *pos)
+{
+ struct cmd_db_header *hdr = m->private;
+ int slv_idx, ent_idx;
+ struct entry_header *ent;
+ int total = 0;
+
+ for (slv_idx = 0; slv_idx < MAX_SLV_ID; slv_idx++) {
+
+ if (!hdr->header[slv_idx].cnt)
+ continue;
+ ent_idx = *pos - total;
+ if (ent_idx < hdr->header[slv_idx].cnt)
+ break;
+
+ total += hdr->header[slv_idx].cnt;
+ }
+
+ if (slv_idx == MAX_SLV_ID)
+ return NULL;
+
+ ent = start_addr + hdr->header[slv_idx].header_offset + sizeof(*hdr);
+ return &ent[ent_idx];
+
+}
+
+static void cmd_db_stop(struct seq_file *m, void *v)
+{
+}
+
+static void *cmd_db_next(struct seq_file *m, void *v, loff_t *pos)
+{
+ (*pos)++;
+ return cmd_db_start(m, pos);
+}
+
+static int cmd_db_seq_show(struct seq_file *m, void *v)
+{
+ struct entry_header *eh = v;
+ struct cmd_db_header *hdr = m->private;
+ char buf[9] = {0};
+
+ if (!eh)
+ return 0;
+
+ memcpy(buf, &eh->res_id, min(sizeof(eh->res_id), sizeof(buf)));
+
+ seq_printf(m, "Address: 0x%05x, id: %s", eh->addr, buf);
+
+ if (eh->len) {
+ int slv_id = (eh->addr >> SLAVE_ID_SHIFT) & SLAVE_ID_MASK;
+ u8 aux[32] = {0};
+ int len;
+ int k;
+
+ len = min_t(u32, eh->len, sizeof(aux));
+
+ for (k = 0; k < MAX_SLV_ID; k++) {
+ if (hdr->header[k].slv_id == slv_id)
+ break;
+ }
+
+ if (k == MAX_SLV_ID)
+ return -EINVAL;
+
+ memcpy_fromio(aux, start_addr + hdr->header[k].data_offset
+ + eh->offset + sizeof(*cmd_db_header), len);
+
+ seq_puts(m, ", aux data: ");
+
+ for (k = 0; k < len; k++)
+ seq_printf(m, "%02x ", aux[k]);
+
+ }
+ seq_puts(m, "\n");
+ return 0;
+}
+
+static const struct seq_operations cmd_db_seq_ops = {
+ .start = cmd_db_start,
+ .stop = cmd_db_stop,
+ .next = cmd_db_next,
+ .show = cmd_db_seq_show,
+};
+
+static int cmd_db_file_open(struct inode *inode, struct file *file)
+{
+ int ret = seq_open(file, &cmd_db_seq_ops);
+ struct seq_file *s = (struct seq_file *)(file->private_data);
+
+ s->private = inode->i_private;
+ return ret;
+}
+
+static const struct file_operations cmd_db_fops = {
+ .owner = THIS_MODULE,
+ .open = cmd_db_file_open,
+ .read = seq_read,
+ .release = seq_release,
+ .llseek = no_llseek,
+};
+
static int cmd_db_dev_probe(struct platform_device *pdev)
{
struct resource res;
@@ -279,6 +384,10 @@ static int cmd_db_dev_probe(struct platform_device *pdev)
cmd_db_status = 0;
of_platform_populate(pdev->dev.of_node, NULL, NULL, &pdev->dev);
+ if (!debugfs_create_file("cmd_db", 0444, NULL,
+ cmd_db_header, &cmd_db_fops))
+ pr_err("Couldn't create debugfs\n");
+
if (cmd_db_is_standalone() == 1)
pr_info("Command DB is initialized in standalone mode.\n");