kernel: Create sysfs interface for BL debug data
Mohit Dhingra [Tue, 29 Apr 2014 11:18:10 +0000 (16:18 +0530)]
Creates a sys-fs interface (debugfs) to read the golden registers
address value pairs passed by bootloader.

Interface created:
/sys/kernel/debug/tegra_bootloader_verify_regs

Bug 866125

Change-Id: I5c78c806f65e938829ef517f8f2974f9b0f16608
Signed-off-by: Mohit Dhingra <mdhingra@nvidia.com>
Reviewed-on: http://git-master/r/402939
Reviewed-by: Bharat Nihalani <bnihalani@nvidia.com>

drivers/platform/tegra/Kconfig
drivers/platform/tegra/Makefile
drivers/platform/tegra/tegra_bootloader_debug.c [new file with mode: 0644]

index 25916fd..2ced451 100644 (file)
@@ -21,3 +21,9 @@ config TEGRA_MC_DOMAINS
        default n
        help
          When enabled, clock gates MC when it's not needed.
+
+config TEGRA_BOOTLOADER_DEBUG
+       tristate "Creates sys-fs interface dumping registers read by bootloader"
+       default n
+       help
+         When enabled, tegra_bootloader_verify_regs sys-fs is created.
index ea12761..db99435 100644 (file)
@@ -8,6 +8,7 @@ obj-$(CONFIG_USB_SUPPORT)               += tegra_usb_pmc.o
 obj-$(CONFIG_TEGRA_USB_SHARED_PAD)      += tegra_usb_pad_ctrl.o
 obj-$(CONFIG_TEGRA_FIQ_DEBUGGER)        += tegra_fiq_debugger.o
 obj-$(CONFIG_TEGRA_IOMMU_SMMU)          += iommu.o
+obj-$(CONFIG_TEGRA_BOOTLOADER_DEBUG)    += tegra_bootloader_debug.o
 
 ifneq ($(CONFIG_ARCH_TEGRA_2x_SOC),y)
 ifneq ($(CONFIG_ARCH_TEGRA_3x_SOC),y)
diff --git a/drivers/platform/tegra/tegra_bootloader_debug.c b/drivers/platform/tegra/tegra_bootloader_debug.c
new file mode 100644 (file)
index 0000000..f67893a
--- /dev/null
@@ -0,0 +1,133 @@
+/*
+ * linux/drivers/platform/tegra/tegra_bootloader_debug.c
+ *
+ * Copyright (C) 2014 NVIDIA Corporation. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/spinlock.h>
+#include <linux/io.h>
+#include <linux/seq_file.h>
+#include <linux/fs.h>
+#include <linux/debugfs.h>
+
+const char *module_name = "tegra_bootloader_debug";
+const char *dir_name = "tegra_bootloader";
+const char *gr_file = "tegra_bootloader_verify_regs";
+
+struct gr_address_value {
+       unsigned int gr_address;
+       unsigned int gr_value;
+};
+
+extern unsigned long tegra_bl_debug_data_start;
+extern unsigned long tegra_bl_debug_data_size;
+
+static int dbg_golden_register_show(struct seq_file *s, void *unused);
+static int dbg_golden_register_open(struct inode *inode, struct file *file);
+static struct dentry *bl_debug_node;
+static struct dentry *bl_debug_verify_reg_node;
+
+static const struct file_operations debug_gr_fops = {
+       .open           = dbg_golden_register_open,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+       .release        = single_release,
+};
+
+static int dbg_golden_register_show(struct seq_file *s, void *unused)
+{
+       struct gr_address_value *gr_memory_dump;
+       int gr_entries = 0;
+       int i;
+
+       gr_entries = tegra_bl_debug_data_size / sizeof(struct gr_address_value);
+
+       gr_memory_dump = (struct gr_address_value *)phys_to_virt(
+                       (phys_addr_t)((struct gr_address_value *)
+                       tegra_bl_debug_data_start));
+
+       for (i = 0; i < gr_entries; i++) {
+               seq_printf(s, "{Address 0x%08x}, {Value 0x%08x}\n",
+                       gr_memory_dump->gr_address, gr_memory_dump->gr_value);
+
+               gr_memory_dump++;
+       }
+
+       return 0;
+}
+
+static int dbg_golden_register_open(struct inode *inode, struct file *file)
+{
+       return single_open(file, dbg_golden_register_show, &inode->i_private);
+}
+
+
+static int __init tegra_bootloader_golden_register_debuginit(void)
+{
+       bl_debug_node = debugfs_create_dir(dir_name, NULL);
+
+       if (!bl_debug_node) {
+               printk(KERN_ERR "%s: failed to create debugfs entries: %ld\n",
+                       module_name, PTR_ERR(bl_debug_node));
+               goto out_err;
+       }
+
+       printk(KERN_INFO "%s: Created %s directory\n", module_name, dir_name);
+
+       bl_debug_verify_reg_node = debugfs_create_file(gr_file, S_IRUGO,
+                               bl_debug_node, NULL, &debug_gr_fops);
+
+       if (!bl_debug_verify_reg_node) {
+               printk(KERN_ERR "%s: failed to create debugfs entries: %ld\n",
+                       module_name, PTR_ERR(bl_debug_verify_reg_node));
+               goto out_err;
+       }
+
+       printk("%s: Created sysfs interface %s in %s directory\n",
+               module_name, gr_file, dir_name);
+
+       return 0;
+
+out_err:
+       if (bl_debug_node)
+               debugfs_remove_recursive(bl_debug_node);
+
+       return -ENODEV;
+}
+
+static int __init tegra_bl_debuginit_module_init(void)
+{
+       tegra_bootloader_golden_register_debuginit();
+       return 0;
+}
+
+static void __exit tegra_bl_debuginit_module_exit(void)
+{
+       printk(KERN_INFO "%s: Exiting\n", module_name);
+       if (bl_debug_node)
+               debugfs_remove_recursive(bl_debug_node);
+
+       bl_debug_node = NULL;
+       bl_debug_verify_reg_node = NULL;
+}
+
+module_init(tegra_bl_debuginit_module_init);
+module_exit(tegra_bl_debuginit_module_exit);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("Driver to enumerate bootloader's debug data");
+MODULE_AUTHOR("Mohit Dhingra <mdhingra@nvidia.com>");